{"openapi":"3.1.0","info":{"title":"DataHub Digiobcan API","description":"Centralized Identity and Access Management","contact":{"name":"Adam Hnat","url":"http://www.bart.sk","email":"hnat@bart.sk"},"version":"1.0.0"},"servers":[{"url":"https://moj.presov.sk/api/v1"}],"paths":{"/me/reports":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get list of reports","operationId":"meGetReports","security":[{"datahubAccount":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0,"maximum":1000},"description":"Number of items to skip for pagination"},{"name":"location","description":"Location in WGS84 format (longitude,latitude,radius_in_meters). Radius is optional.","in":"query","schema":{"type":"string","example":"20.123456,49.123456 or 20.123456,49.123456,1000"}},{"name":"orderBy","in":"query","required":false,"schema":{"type":"string","enum":["date","location","votes"],"default":"date"},"description":"Order reports by date, location or number of votes"},{"name":"orderDirection","in":"query","schema":{"type":"string","enum":["asc","desc"]},"description":"Default is 'desc'"}],"responses":{"200":{"description":"A list of reports","content":{"application/json":{"schema":{"type":"object","required":["reports","hasNextOffset","offset","limit"],"properties":{"reports":{"type":"array","items":{"allOf":[{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Riadok zoznamu vlastnych podnetov. Jeden **podnet**, nie jeden nalez.\n\n`status` je preto derivovany zo stavov vsetkych jeho nalezov, presne\nako na `ReportDetail` a `AdminReportListItem`: podnet je `resolved`\naz vtedy, ked je vyrieseny **kazdy** jeho nalez. Bez neho sa\nv zozname nedalo rozlisit vyrieseny podnet od podaneho - `accepted`\nje pri vyriesenom `false`, takze taky podnet hlasil obcanovi\n„Podane\" aj mesiac po tom, co ho mesto uzavrelo.\n\n`accepted` zostava, aby starsi frontend nezostal bez stavu vobec.\n","additionalProperties":false,"required":["accepted"],"properties":{"description":{"type":"string","description":"Description of the report"},"accepted":{"type":"boolean"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"}}}]},{"type":"object","properties":{"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"}}}]}},"hasNextOffset":{"type":"boolean","description":"Indicates if there are more items available for pagination"},"offset":{"type":"integer","description":"The offset value used for this request"},"limit":{"type":"integer","description":"The limit value used for this request"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/reports-categories":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get my report categories","operationId":"meGetReportCategories","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"List of report categories assigned to the user","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object","required":["name","category_id","is_default"],"properties":{"name":{"type":"string"},"category_id":{"type":"string"},"is_default":{"type":"boolean","description":"Predvolena kategoria pre nezaradene podnety. Zoznam\nv administracii ju radi na koniec - je to cakaren,\nnie utvar, ktory nieco riesi.\n"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/news-categories":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get my news categories subscriptions","operationId":"meGetNewsCategories","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"A list of subscriptions","content":{"application/json":{"schema":{"type":"object","required":["subscriptions"],"properties":{"subscriptions":{"type":"array","items":{"type":"string"}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"patch":{"tags":["Me"],"description":"Update my news categories subscriptions","operationId":"meUpdateNewsCategories","security":[{"datahubAccount":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","required":["category_id","subscribed"],"properties":{"category_id":{"type":"string"},"subscribed":{"type":"boolean"}}}}}}},"responses":{"200":{"description":"Update was successful","content":{"application/json":{"schema":{"type":"object","required":["changes"],"properties":{"changes":{"type":"number"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/vote-tokens":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get list of all vote tokens used by the user, sorted by creation date (newest first).\nCan be filtered by active status.\n","operationId":"meGetVoteTokens","security":[{"datahubAccount":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"string"}},"description":"Array of inserted_at (ISO string) and token_id to use as cursor for pagination.\nFormat: [\"2023-07-21T10:30:00.000Z\", \"token-123\"]\n"},{"name":"active","in":"query","required":false,"schema":{"type":"boolean"},"description":"Filter tokens by active status:\n- true: only active tokens (not revoked and not expired)\n- false: only inactive tokens (revoked or expired)\n- undefined: all tokens\n"}],"responses":{"200":{"description":"List of vote tokens used by the user","content":{"application/json":{"schema":{"type":"object","required":["tokens"],"properties":{"tokens":{"type":"array","items":{"type":"object","required":["token_id","target"],"properties":{"token_id":{"type":"string","description":"Unique identifier of the token"},"target":{"type":"string","description":"Target for which the token was generated"},"inserted_at":{"type":"string","format":"date-time","description":"When the token was inserted"},"expires_at":{"type":"string","format":"date-time","description":"When the token expires (optional, some tokens may not have expiration)"},"revoked_at":{"type":"string","format":"date-time","description":"When the token was revoked (if applicable)"}}}},"nextCursor":{"anyOf":[{"type":"array","minItems":3,"maxItems":3,"items":{"type":"string"}},{"type":"null"}],"description":"Cursor for next page of results"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Me"],"description":"Generate votes for a target","operationId":"meVoteToken","security":[{"datahubAccount":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["target","count"],"properties":{"target":{"type":"string"},"count":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Vote tokens generated successfully","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/vote-tokens/{targetId}":{"x-controller-name":"me.ctrl","parameters":[{"name":"targetId","in":"path","required":true,"schema":{"type":"string"},"description":"Target ID to get token status for"}],"get":{"tags":["Me"],"description":"How the signed-in citizen stands on this one target: how many of their votes\nare on it, and how many they still have left in their pool. Votes have no\ntype, so this is a single pair of numbers, not a list.\n","operationId":"meGetTargetVoteTokens","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"Vote status retrieved successfully","content":{"application/json":{"schema":{"type":"object","required":["active_tokens","available_tokens"],"properties":{"active_tokens":{"type":"integer","description":"Number of the user's active (non-expired, non-revoked) votes\non this target. Non-zero means the user has already voted.\n"},"available_tokens":{"type":"integer","description":"Number of votes the user still has left in their pool. This is\nthe whole pool, not a per-target figure.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/vote-tokens-summary":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"The signed-in citizen's vote pool as a whole, across every target.\nNamed `summary` and not `types` because votes have no type - the pool is\none number in, one number out.\n","operationId":"meGetVoteTokensSummary","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"Vote pool retrieved successfully","content":{"application/json":{"schema":{"type":"object","required":["active_tokens","available_tokens","max_count"],"properties":{"active_tokens":{"type":"integer","description":"Votes the user currently has cast and that still count -\nnot revoked and not expired.\n"},"available_tokens":{"type":"integer","description":"Votes the user can still cast (`max_count - active_tokens`)."},"max_count":{"type":"integer","description":"Size of the pool. Configured per environment\n(`users_tokens.max_count`), the same for every account.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/vote-token-revoke":{"x-controller-name":"me.ctrl","patch":{"tags":["Me"],"description":"Revoke votes for a target","operationId":"meVoteTokenRevoke","security":[{"datahubAccount":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["target","count"],"properties":{"target":{"type":"string"},"count":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Vote tokens revoked successfully","content":{"application/json":{"schema":{"type":"object","properties":{"revoked_count":{"type":"integer","description":"Number of tokens that were actually revoked"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/notifications":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get my notifications","operationId":"meGetNotifications","security":[{"datahubAccount":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"string"}},"description":"Array of sent_at (ISO string) and inserted_at (ISO string) to use as cursor for pagination.\nFormat: [\"2023-07-21T10:30:00.000Z\", \"2023-07-20T10:30:00.000Z\"]\n"}],"responses":{"200":{"description":"A list of notifications","content":{"application/json":{"schema":{"type":"object","required":["notifications","hasNextOffset"],"properties":{"notifications":{"type":"array","items":{"type":"object","required":["tag","title","sent_at"],"properties":{"tag":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"url":{"type":"string","format":"uri"},"sent_at":{"type":"string","format":"date-time","description":"Date of the notification in ISO 8601 format"},"icon":{"type":"string","description":"URL to the icon"},"inserted_at":{"type":"string","format":"date-time","description":"Inserted date in ISO 8601 format"},"read_at":{"type":"string","format":"date-time","description":"Date when the notification was read in ISO 8601 format"}}}},"hasNextOffset":{"type":"boolean"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/notifications/read":{"x-controller-name":"me.ctrl","patch":{"tags":["Me"],"description":"Mark my notifications as read by tags\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: INVALID_NOTIFICATION_TAGS\n","operationId":"meNotificationsMarkAsRead","security":[{"datahubAccount":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["notificationTags"],"properties":{"notificationTags":{"type":"array","items":{"type":"string"},"description":"Tags of notification tags to be marked as read","minItems":1}}}}}},"responses":{"200":{"description":"Notifications marked as read successfully","content":{"application/json":{"schema":{"type":"object","required":["notifications","unread_count"],"properties":{"notifications":{"type":"array","items":{"type":"object","required":["tag","title","sent_at"],"properties":{"tag":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"url":{"type":"string","format":"uri"},"sent_at":{"type":"string","format":"date-time","description":"Date of the notification in ISO 8601 format"},"icon":{"type":"string","description":"URL to the icon"},"inserted_at":{"type":"string","format":"date-time","description":"Inserted date in ISO 8601 format"},"read_at":{"type":"string","format":"date-time","description":"Date when the notification was read in ISO 8601 format"}}}},"unread_count":{"type":"number","description":"Number of unread notifications (max 10)","maximum":10,"minimum":0}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/notifications/unread-count":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get count of my unread notifications (max 10)","operationId":"meGetNotificationsUnreadCount","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"Count of unread notifications","content":{"application/json":{"schema":{"type":"object","required":["unread_count"],"properties":{"unread_count":{"type":"number","description":"Number of unread notifications (max 10)","maximum":10,"minimum":0}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/notifications/settings":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get my notification settings","operationId":"meGetNotificationsSettings","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"Notification settings retrieved successfully","content":{"application/json":{"schema":{"type":"object","required":["enabled","interval"],"properties":{"enabled":{"type":"boolean","description":"Whether notifications are enabled"},"interval":{"type":"string","enum":["daily","weekly","monthly"],"nullable":true,"description":"Notification frequency"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"put":{"tags":["Me"],"description":"Update user notification settings","operationId":"meUpdateNotificationsSettings","security":[{"datahubAccount":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled","interval"],"properties":{"enabled":{"type":"boolean","description":"Whether notifications are enabled"},"interval":{"type":"string","enum":["daily","weekly","monthly"],"nullable":true,"description":"Notification frequency"}}}}}},"responses":{"200":{"description":"Notification settings updated successfully","content":{"application/json":{"schema":{"type":"object","required":["enabled","interval"],"properties":{"enabled":{"type":"boolean","description":"Whether notifications are enabled"},"interval":{"type":"string","enum":["daily","weekly","monthly"],"nullable":true,"description":"Notification frequency"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/notifications/webpush":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get user's web push notifications status","operationId":"meNotificationsWebPushStatus","security":[{"datahubAccount":[]}],"parameters":[{"name":"endpoint","in":"query","required":true,"schema":{"type":"string"},"description":"URL to the push service endpoint to be checked"}],"responses":{"200":{"description":"User's web push notifications status","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"boolean"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Me"],"operationId":"meNotificationsWebPushSubscribe","description":"Subscribe user to web push notifications","security":[{"datahubAccount":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["endpoint","keys"],"properties":{"endpoint":{"type":"string","description":"URL to the push service endpoint"},"keys":{"type":"object","required":["p256dh","auth"],"properties":{"p256dh":{"type":"string","description":"Base64 encoded public key"},"auth":{"type":"string","description":"Base64 encoded authentication secret"}}}}}}}},"responses":{"201":{"description":"WebPush subscription registered successfully","content":{"application/json":{"schema":{"type":"object","required":["subscription"],"properties":{"subscription":{"type":"object","required":["endpoint","keys"],"properties":{"endpoint":{"type":"string","description":"URL to the push service endpoint"},"keys":{"type":"object","required":["p256dh","auth"],"properties":{"p256dh":{"type":"string","description":"Base64 encoded public key"},"auth":{"type":"string","description":"Base64 encoded authentication secret"}}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"delete":{"tags":["Me"],"parameters":[{"name":"endpoint","in":"query","required":true,"schema":{"type":"string"},"description":"URL to the push service endpoint to be deleted"}],"description":"Unsubscribe user from web push notifications\n\nChyby, ktoré môže endpoint vrátiť:\n- 404: WEBPUSH_SUBSCRIPTION_NOT_FOUND\n","operationId":"meNotificationsWebPushUnsubscribe","security":[{"datahubAccount":[]}],"responses":{"201":{"description":"WebPush subscription deleted successfully","content":{"application/json":{"schema":{"type":"object","required":["endpoint"],"properties":{"endpoint":{"type":"string","description":"URL to the push service endpoint"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/me/notifications/email":{"x-controller-name":"me.ctrl","get":{"tags":["Me"],"description":"Get user's email notifications status","operationId":"meNotificationsEmailStatus","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"User's email notifications status","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"boolean"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Me"],"operationId":"meNotificationsEmailSubscribe","security":[{"datahubAccount":[]}],"responses":{"201":{"description":"Notification registered successfully","content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"delete":{"tags":["Me"],"description":"Unsubscribe user from email notifications","operationId":"meNotificationsEmailUnsubscribe","security":[{"datahubAccount":[]}],"responses":{"201":{"description":"Email subscription deleted successfully","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","example":"Email subscription deleted successfully"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/projects":{"x-controller-name":"projects.ctrl","get":{"tags":["Projects"],"description":"Get list of visible projects","operationId":"getProjects","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"string"}},"description":"Array of open_from (ISO string) and project_id to use as cursor for pagination.\nFormat: [\"2023-07-21T10:30:00.000Z\", \"voting-123\"]\n"}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"type":"object","required":["projects"],"properties":{"projects":{"type":"array","items":{"type":"object","required":["project_id","title","inserted_at"],"properties":{"project_id":{"type":"string"},"title":{"type":"string"},"inserted_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/projects/{projectId}":{"x-controller-name":"projects.ctrl","parameters":[{"name":"projectId","in":"path","required":true,"description":"Project ID","schema":{"type":"string"}}],"get":{"tags":["Projects"],"description":"Get visible project detail","operationId":"getProjectDetail","responses":{"200":{"description":"Project detail","content":{"application/json":{"schema":{"type":"object","required":["project_id","title","description","media","inserted_at"],"properties":{"project_id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["PROJECT_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/news":{"x-controller-name":"news.ctrl","get":{"tags":["News"],"description":"Get datahub news","operationId":"getNews","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"location","description":"Location in WGS84 format (longitude,latitude,radius_in_meters). Radius is optional.","in":"query","schema":{"type":"string","example":"20.123456,49.123456 or 20.123456,49.123456,1000"}},{"name":"category","in":"query","required":false,"description":"Category Ids to filter news","schema":{"type":"array","items":{"type":"string"}}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":1,"maxItems":2,"items":{"type":"string"}},"description":"Cursor for pagination with different formats based on sorting:\n- With location parameter: [\"distance\", \"news_id\"] - Distance in meters and news_id for location-based sorting (or \"null\" for news without location)\n- Without location parameter: [\"date_iso\", \"news_id\"] - Date (ISO string) and news_id for date-based sorting\nExamples:\n- Location-based: [\"500.2\", \"urn:ngsi-ld:presov.sk:digital-obcan:spr:123\"]\n- Location-based (no location): [\"null\", \"urn:ngsi-ld:presov.sk:digital-obcan:spr:123\"]\n- Date-based: [\"2023-07-21T10:30:00.000Z\", \"urn:ngsi-ld:presov.sk:digital-obcan:spr:123\"]\n"}],"responses":{"200":{"description":"A list of news","content":{"application/json":{"schema":{"type":"object","required":["news"],"properties":{"news":{"type":"array","items":{"required":["id"],"type":"object","properties":{"id":{"type":"string"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"title":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","description":"URL to the image"},"date":{"type":"string","format":"date-time","description":"Date of the news in ISO 8601 format"},"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"},"categories":{"type":"array","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}},"nextCursor":{"type":"array","minItems":1,"maxItems":2,"items":{"type":"string"},"description":"Cursor for next page of results.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/news/{newId}":{"x-controller-name":"news.ctrl","get":{"tags":["News"],"description":"Get datahub news item by ID\n\nChyby, ktoré môže endpoint vrátiť:\n- 404: NEWS_ITEM_NOT_FOUND\n","operationId":"getNewsDetail","parameters":[{"name":"newId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"A single news item","content":{"application/json":{"schema":{"required":["id"],"type":"object","properties":{"id":{"type":"string"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"title":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","description":"URL to the image"},"date":{"type":"string","format":"date-time","description":"Date of the news in ISO 8601 format"},"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"},"categories":{"type":"array","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/news-categories":{"x-controller-name":"news.ctrl","get":{"tags":["News:Categories"],"parameters":[{"in":"query","name":"view","schema":{"type":"string","enum":["flat","tree"],"default":"flat"},"description":"If true, returns a property children."}],"description":"Get list of existing news categories","operationId":"getNewsCategories","responses":{"200":{"description":"A list of categories","content":{"application/json":{"schema":{"type":"object","required":["news_categories"],"properties":{"news_categories":{"type":"array","items":{"allOf":[{"type":"object","required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}},{"type":"object","properties":{"children":{"type":"array","items":{"type":"object","required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}}}}}]}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["News:Categories"],"description":"Creates a new category","operationId":"createNewsCategory","security":[{"datahubAccount":["pruser:news-categories:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Created category","content":{"application/json":{"schema":{"type":"object","required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/news-categories/{categoryId}":{"delete":{"x-controller-name":"news.ctrl","tags":["News:Categories"],"description":"Deletes a category based on provided ID\n\nChyby, ktoré môže endpoint vrátiť:\n- 404: CATEGORY_NOT_FOUND\n","operationId":"deleteNewsCategory","security":[{"datahubAccount":["pruser:news-categories:manage"]}],"parameters":[{"name":"categoryId","in":"path","required":true,"description":"Category ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted the category"},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"put":{"x-controller-name":"news.ctrl","tags":["News:Categories"],"description":"Updates a news category","operationId":"updateNewsCategory","security":[{"datahubAccount":["pruser:news-categories:manage"]}],"parameters":[{"name":"categoryId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"parent_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated category","content":{"application/json":{"schema":{"type":"object","required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports":{"x-controller-name":"reports.ctrl","get":{"tags":["Reports"],"description":"Get all public reports","operationId":"getReports","security":[{"optionalDatahubAccount":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"location","description":"Location in WGS84 format (longitude,latitude,radius_in_meters). Radius is optional.","in":"query","schema":{"type":"string","example":"20.123456,49.123456 or 20.123456,49.123456,1000"}},{"name":"category","in":"query","required":false,"description":"Category Ids to filter reports","schema":{"type":"array","items":{"type":"string"}}},{"name":"status","in":"query","required":false,"description":"Status to filter reports","schema":{"type":"array","items":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]}}},{"name":"q","in":"query","required":false,"description":"Hladany text. Hlada sa v nazve, popise a identifikatore podnetu,\nbez ohladu na velkost pismen a na diakritiku - `vytluk` najde aj\n`Výtluk`.\n","schema":{"type":"string","minLength":1}},{"name":"orderBy","in":"query","required":false,"schema":{"type":"string","enum":["date","location","votes"],"default":"date"},"description":"Order reports by date, location or number of votes"},{"name":"orderDirection","in":"query","schema":{"type":"string","enum":["asc","desc"]},"description":"Default is 'desc'"},{"name":"dateFrom","in":"query","required":false,"description":"Filter reports from this date (ISO 8601 format)","schema":{"type":"string","format":"date-time"}},{"name":"dateTo","in":"query","required":false,"description":"Filter reports until this date (ISO 8601 format)","schema":{"type":"string","format":"date-time"}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0,"maximum":1000},"description":"Number of items to skip for pagination"}],"responses":{"200":{"description":"A list of public reports","content":{"application/json":{"schema":{"type":"object","required":["reports","hasNextOffset","offset","limit"],"properties":{"reports":{"type":"array","items":{"allOf":[{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Detail podnetu pre obcana - jeden **podnet**, nie jeden nalez.\n\nPreto je tu `status` **derivovany zo stavov vsetkych jeho nalezov**:\nvyhrava najmenej pokrocily (`open` > `accepted` > `duplicate` >\n`resolved`), presne ako na `AdminReportListItem`. Podnet je teda\n`resolved` az vtedy, ked je vyrieseny **kazdy** jeho nalez.\nPresunute (`moved`) nalezy do derivacie nevstupuju; podnet, ktory\nma len take, stav nema. Riadok `GET /reports` je oproti tomu jeden\nnalez, takze tam to iste pole nesie stav toho jedneho nalezu.\n\nBez `status` sa uzavretost podnetu z verejneho API odvodit neda:\n`/reports/{reportId}/status` nesie len nalezy, ktore sa uz rozhybali\n(`accepted`, `duplicate`, `resolved`), takze nalez v stave `open`\nv nej krok vobec nema.\n","properties":{"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"description":{"type":"string"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]}}}]},{"type":"object","properties":{"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"}}}]}},"hasNextOffset":{"type":"boolean","description":"Indicates if there are more items available for pagination"},"offset":{"type":"integer","description":"The offset value used for this request"},"limit":{"type":"integer","description":"The limit value used for this request"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Me"],"description":"Create a new report\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: NO_MEDIA, TOTAL_MEDIA_SIZE_TOO_LARGE, REPORT_INVALID_LOCATION, REPORT_OUTSIDE_CITY\n- 403: RECAPTCHA_VERIFICATION_FAILED\n\n`REPORT_OUTSIDE_CITY` znamená, že poloha leží mimo územia mesta Prešov.\nTen istý polygón, podľa ktorého sa to posudzuje, vydáva `GET /geo/boundary`.\n","operationId":"createReport","security":[{"optionalDatahubAccount":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","additionalProperties":false,"required":["title","description"],"properties":{"title":{"type":"string","maxLength":256},"description":{"type":"string","maxLength":2048},"location":{"description":"Location in WGS84 format (longitude,latitude[,radius]).\nNepovinné - podnet bez polohy je platný. Ak je uvedená, musí\nbyť čitateľná a musí ležať na území mesta Prešov, inak\nendpoint vráti 400 (REPORT_INVALID_LOCATION alebo\nREPORT_OUTSIDE_CITY).\n","type":"string","example":"21.239311,49.001831"},"media":{"type":"array","items":{"type":"string","format":"binary"}},"recaptchaToken":{"type":"string","description":"reCAPTCHA v3 response token. Required when user is not authenticated."}}}}}},"responses":{"201":{"description":"Report created successfully","content":{"application/json":{"schema":{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports/{reportId}":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"get":{"tags":["Reports"],"description":"Get public report detail by ID","operationId":"getReportDetail","security":[{"optionalDatahubAccount":[]}],"responses":{"200":{"description":"A single public report item","content":{"application/json":{"schema":{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Detail podnetu pre obcana - jeden **podnet**, nie jeden nalez.\n\nPreto je tu `status` **derivovany zo stavov vsetkych jeho nalezov**:\nvyhrava najmenej pokrocily (`open` > `accepted` > `duplicate` >\n`resolved`), presne ako na `AdminReportListItem`. Podnet je teda\n`resolved` az vtedy, ked je vyrieseny **kazdy** jeho nalez.\nPresunute (`moved`) nalezy do derivacie nevstupuju; podnet, ktory\nma len take, stav nema. Riadok `GET /reports` je oproti tomu jeden\nnalez, takze tam to iste pole nesie stav toho jedneho nalezu.\n\nBez `status` sa uzavretost podnetu z verejneho API odvodit neda:\n`/reports/{reportId}/status` nesie len nalezy, ktore sa uz rozhybali\n(`accepted`, `duplicate`, `resolved`), takze nalez v stave `open`\nv nej krok vobec nema.\n","properties":{"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"description":{"type":"string"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports/{reportId}/status":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"get":{"tags":["Me"],"description":"Get my report status","operationId":"getReportStatus","security":[{"optionalDatahubAccount":[]}],"responses":{"200":{"description":"Chronological list of report statuses","content":{"application/json":{"schema":{"type":"object","required":["statuses"],"properties":{"statuses":{"type":"array","items":{"type":"object","description":"Jeden krok casovej osi podnetu tak, ako ju vidi obcan: nalez, ktory\nurad prijal (`accepted`), uzavrel (`resolved`) alebo zlucil ako duplikat\n(`duplicate`), plus vyjadrenia, ktore k nemu urad zverejnil.\n\nPri `duplicate` su vo `statements` vyjadrenia **originalu**, nie tohto\nnalezu - duplikat preberá riesenie aj vyjadrenie toho, do ktoreho bol\nzluceny, a vlastne stanovisko sa nezverejnuje.\n","required":["status","date","categoryName"],"properties":{"issue_id":{"type":"string","description":"Nalez, ktoreho sa krok tyka"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"date":{"type":"string","format":"date-time","description":"Date of the status change in ISO 8601 format"},"categoryName":{"type":"string","description":"Name of the category associated with the status"},"statements":{"type":"array","description":"Zverejnene vyjadrenia uradu, od najnovsieho.","items":{"type":"object","description":"Vyjadrenie tak, ako ho vidi obcan. Je to `IssueStatement` **bez autora**:\nzverejnuje sa stanovisko uradu, nie meno konkretneho uradnika.\n","required":["statement_id","text","final","media","inserted_at"],"properties":{"statement_id":{"type":"string"},"text":{"type":"string"},"final":{"type":"boolean"},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"}}}}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/reports":{"x-controller-name":"reports.ctrl","get":{"tags":["Reports"],"description":"Returns all reports that the admin has the right to see.\n\nJeden prvok `reports` je jeden podnet, nie jeden nalez: nalezy\npodnetu su v poli `issues` a `status` je z nich derivovany. Filtre\n`category`, `status` a `overdue` vyberaju podnety, ktore maju aspon\njeden pristupny nalez zodpovedajuci filtru - `issues` v odpovedi vsak\nobsahuje vsetky pristupne nalezy podnetu, aby zoznam ukazal cely\nkontext, nielen tu cast, na ktoru sa filtrovalo.\n","operationId":"adminGetReports","security":[{"datahubAccount":["pruser:reports:read"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0,"maximum":1000},"description":"Number of items to skip for pagination"},{"name":"category","in":"query","required":false,"description":"Category Ids to filter reports","schema":{"type":"array","items":{"type":"string"}}},{"name":"status","in":"query","required":false,"description":"Status to filter reports","schema":{"type":"array","items":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]}}},{"name":"q","in":"query","required":false,"description":"Hladany text. Hlada sa v nazve, popise a identifikatore podnetu,\nbez ohladu na velkost pismen a na diakritiku - `vytluk` najde aj\n`Výtluk`.\n","schema":{"type":"string","minLength":1}},{"name":"orderBy","in":"query","schema":{"type":"string","enum":["votes","date","location"]},"description":"Default is 'date'"},{"name":"orderDirection","in":"query","schema":{"type":"string","enum":["asc","desc"]},"description":"Default is 'desc'"},{"name":"dateFrom","in":"query","required":false,"description":"Filter reports from this date (ISO 8601 format)","schema":{"type":"string","format":"date-time"}},{"name":"dateTo","in":"query","required":false,"description":"Filter reports until this date (ISO 8601 format)","schema":{"type":"string","format":"date-time"}},{"name":"location","description":"Location in WGS84 format (longitude,latitude,radius_in_meters). Radius is optional.","in":"query","schema":{"type":"string","example":"20.123456,49.123456 or 20.123456,49.123456,1000"}},{"name":"overdue","in":"query","required":false,"description":"Filtrovanie podla lehoty na vyjadrenie:\n- true: len podnety po lehote (lehota uplynula a issue je nevyriesena)\n- false: len podnety v lehote alebo uz vyriesene\n- neuvedene: bez filtra\n","schema":{"type":"boolean"}}],"responses":{"200":{"description":"A list of reports","content":{"application/json":{"schema":{"type":"object","required":["reports","hasNextOffset","offset","limit"],"properties":{"reports":{"type":"array","items":{"allOf":[{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Riadok zoznamu podnetov pre admina - jeden podnet, nie jeden\nnalez. `status` je stav celeho podnetu derivovany zo stavov\nnalezov v `issues`: vyhrava najmenej pokrocily stav, aby riadok\nvzdy priznal, ze podnet este nieco potrebuje\n(`open` > `accepted` > `duplicate` > `resolved`). Podnet je teda\n`resolved` az vtedy, ked je vyrieseny kazdy pristupny nalez.\nBez `issues` je nedefinovany.\n","properties":{"issue_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - riadok je podnet,\nktore moze mat viac nalezov. Zoznam nalezov je v `issues`.\n"},"category_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - kategorie podnetu\nsu v `issues`.\n"},"issues":{"type":"array","description":"Nalezy podnetu, ktore ma prihlaseny admin pravo vidiet -\nsuperadmin (`pruser:report-categories:access-all`) vsetky,\nostatni len tie vo svojich kategoriach. Presunute (`moved`)\nnalezy v zozname nie su, rovnako ako v tabulke nalezov v detaile.\nRiadok zoznamu je jeden podnet, nie jeden nalez.\nDetail podnetu toto pole nevracia - ma na nalezy vlastny\nendpoint `/admin/reports/{reportId}/issues`.\n","items":{"type":"object","description":"Nalez (issue) podnetu - podnet v konkretnej kategorii - tak, ako ho\nvidi prihlaseny admin v zozname podnetov.\n","required":["issue_id","category_id","status","inserted_at"],"properties":{"issue_id":{"type":"string","description":"Identifikator nalezu"},"category_id":{"type":"string","description":"Kategoria, v ktorej je podnet vedeny"},"category_name":{"type":"string","description":"Nazov kategorie"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Datum zaradenia podnetu do kategorie"},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates`, nie zo stavu - `possible_duplicate`\nako stav zanikol. Priznak zhasne, ked uradnik navrhy zamietne\n(`dismiss_duplicates`) alebo ked sa nalez stane duplikatom.\n"}}}},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and\nnot expired. Votes have no type and no weight, so this is the whole\nstory: one citizen's vote is one.\n"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"submitted_at":{"type":"string","format":"date-time","description":"Datum podania podnetu obcanom (digiobcan.reports.inserted_at).\nV zozname pre admina je totozny s `inserted_at` - riadok je cele\npodnet, takze aj `inserted_at` je datum jeho podania, nie\ndatum vzniku nalezu (ten je na kazdom prvku `issues`).\n`deadline_at` sa pocita z tohto pola.\n"},"deadline_at":{"type":"string","format":"date-time","description":"Lehota na vyjadrenie - datum podania podnetu\n(submitted_at) + N kalendarnych dni.\nN je konfigurovatelne cez `reports.responseDeadlineDays`.\n"},"overdue":{"type":"boolean","description":"true, ak lehota na vyjadrenie uz uplynula a aspon jeden\nz pristupnych nalezov podnetu je stale nepridelen[y]\n(status `open`). Lehota bezi po **prijatie** nalezu, nie po\njeho vyriesenie. Rovnako to plati v zozname aj v detaile.\n"}}}]},{"type":"object","properties":{"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"}}}]}},"hasNextOffset":{"type":"boolean","description":"Indicates if there are more items available for pagination"},"offset":{"type":"integer","description":"The offset value used for this request"},"limit":{"type":"integer","description":"The limit value used for this request"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/reports/{reportId}":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"get":{"tags":["Reports"],"description":"Get report detail by ID\n\nChyby, ktoré môže endpoint vrátiť:\n- 403: REPORTS_ACCESS_FORBIDDEN\n- 404: REPORTS_ITEM_NOT_FOUND\n","operationId":"adminGetReportDetail","security":[{"datahubAccount":["pruser:reports:read"]}],"responses":{"200":{"description":"A single report item","content":{"application/json":{"schema":{"allOf":[{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Riadok zoznamu podnetov pre admina - jeden podnet, nie jeden\nnalez. `status` je stav celeho podnetu derivovany zo stavov\nnalezov v `issues`: vyhrava najmenej pokrocily stav, aby riadok\nvzdy priznal, ze podnet este nieco potrebuje\n(`open` > `accepted` > `duplicate` > `resolved`). Podnet je teda\n`resolved` az vtedy, ked je vyrieseny kazdy pristupny nalez.\nBez `issues` je nedefinovany.\n","properties":{"issue_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - riadok je podnet,\nktore moze mat viac nalezov. Zoznam nalezov je v `issues`.\n"},"category_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - kategorie podnetu\nsu v `issues`.\n"},"issues":{"type":"array","description":"Nalezy podnetu, ktore ma prihlaseny admin pravo vidiet -\nsuperadmin (`pruser:report-categories:access-all`) vsetky,\nostatni len tie vo svojich kategoriach. Presunute (`moved`)\nnalezy v zozname nie su, rovnako ako v tabulke nalezov v detaile.\nRiadok zoznamu je jeden podnet, nie jeden nalez.\nDetail podnetu toto pole nevracia - ma na nalezy vlastny\nendpoint `/admin/reports/{reportId}/issues`.\n","items":{"type":"object","description":"Nalez (issue) podnetu - podnet v konkretnej kategorii - tak, ako ho\nvidi prihlaseny admin v zozname podnetov.\n","required":["issue_id","category_id","status","inserted_at"],"properties":{"issue_id":{"type":"string","description":"Identifikator nalezu"},"category_id":{"type":"string","description":"Kategoria, v ktorej je podnet vedeny"},"category_name":{"type":"string","description":"Nazov kategorie"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Datum zaradenia podnetu do kategorie"},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates`, nie zo stavu - `possible_duplicate`\nako stav zanikol. Priznak zhasne, ked uradnik navrhy zamietne\n(`dismiss_duplicates`) alebo ked sa nalez stane duplikatom.\n"}}}},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and\nnot expired. Votes have no type and no weight, so this is the whole\nstory: one citizen's vote is one.\n"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"submitted_at":{"type":"string","format":"date-time","description":"Datum podania podnetu obcanom (digiobcan.reports.inserted_at).\nV zozname pre admina je totozny s `inserted_at` - riadok je cele\npodnet, takze aj `inserted_at` je datum jeho podania, nie\ndatum vzniku nalezu (ten je na kazdom prvku `issues`).\n`deadline_at` sa pocita z tohto pola.\n"},"deadline_at":{"type":"string","format":"date-time","description":"Lehota na vyjadrenie - datum podania podnetu\n(submitted_at) + N kalendarnych dni.\nN je konfigurovatelne cez `reports.responseDeadlineDays`.\n"},"overdue":{"type":"boolean","description":"true, ak lehota na vyjadrenie uz uplynula a aspon jeden\nz pristupnych nalezov podnetu je stale nepridelen[y]\n(status `open`). Lehota bezi po **prijatie** nalezu, nie po\njeho vyriesenie. Rovnako to plati v zozname aj v detaile.\n"}}}]},{"type":"object","properties":{"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"description":{"type":"string"},"issuedReportCategories":{"type":"array","description":"List of unique category IDs this report belongs to","items":{"type":"string","description":"Category ID"}}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"patch":{"tags":["Reports"],"description":"Update ReportDetail flags","operationId":"adminUpdateReport","security":[{"datahubAccount":["pruser:reports:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["explicit"],"properties":{"explicit":{"type":"boolean","description":"Indicates whether the report is explicit"}}}}}},"responses":{"200":{"description":"Returns status of report detail","content":{"application/json":{"schema":{"type":"object","properties":{"explicit":{"type":"boolean","description":"Indicates whether the report is explicit"}}}}}}}}},"/admin/reports/{reportId}/status":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"patch":{"tags":["Reports"],"description":"Change status of an accessible report\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: INVALID_ISSUE_STATUS_UPDATE, ISSUE_ALREADY_ACCEPTED, EXISTING_ISSUES_IN_CATEGORIES, ISSUE_NOT_FOUND, INVALID_ACTION\n- 403: FORBIDDEN_ISSUE_STATE_UPDATE\n","operationId":"adminUpdateReportStatus","security":[{"datahubAccount":["pruser:reports:manage"]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["category_id","status"],"properties":{"category_id":{"type":"string"},"status":{"type":"string","enum":["accepted","moved"]},"new_category_ids":{"type":"array","items":{"type":"string"}},"current_issue_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Status successfully updated","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["status","issue_id"],"properties":{"status":{"type":"string","enum":["accepted"]},"issue_id":{"type":"string"}}},{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["moved"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/reports/{reportId}/issues":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"get":{"tags":["Reports"],"description":"Get report issues by report ID","operationId":"adminGetReportIssues","security":[{"datahubAccount":["pruser:reports:read"]}],"responses":{"200":{"description":"A single report item","content":{"application/json":{"schema":{"type":"object","required":["issues"],"properties":{"issues":{"type":"array","items":{"type":"object","required":["id","report_id","category_id","category_name","status","inserted_at"],"properties":{"id":{"type":"string"},"report_id":{"type":"string"},"category_id":{"type":"string"},"category_name":{"type":"string"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"parent_id":{"type":"string"},"parent_report_id":{"type":"string"},"resolved_at":{"type":"string","format":"date-time","description":"Kedy nalez presiel do stavu `resolved`. Chyba, ak nie je vyrieseny."},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates` - viz `ReportStatus`.\n"},"possible_duplicates_count":{"type":"integer","description":"Pocet navrhov na duplicitu. 0, ked ziadne nie su."},"statements_count":{"type":"integer","description":"Pocet vyjadreni k nalezu vratane finalneho."}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/reports/{reportId}/duplicates":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"get":{"tags":["Reports"],"description":"Get all duplicate issues for a report","operationId":"adminGetReportDuplicates","security":[{"datahubAccount":["pruser:reports:read"]}],"responses":{"200":{"description":"List of duplicate issues","content":{"application/json":{"schema":{"type":"object","required":["duplicates"],"properties":{"duplicates":{"type":"array","items":{"type":"object","required":["id","report_id","category_id","category_name","status","inserted_at"],"properties":{"id":{"type":"string"},"report_id":{"type":"string"},"category_id":{"type":"string"},"category_name":{"type":"string"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"parent_id":{"type":"string"},"parent_report_id":{"type":"string"},"resolved_at":{"type":"string","format":"date-time","description":"Kedy nalez presiel do stavu `resolved`. Chyba, ak nie je vyrieseny."},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates` - viz `ReportStatus`.\n"},"possible_duplicates_count":{"type":"integer","description":"Pocet navrhov na duplicitu. 0, ked ziadne nie su."},"statements_count":{"type":"integer","description":"Pocet vyjadreni k nalezu vratane finalneho."}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/issues/{issueId}/possible-duplicates":{"x-controller-name":"reports.ctrl","parameters":[{"name":"issueId","in":"path","required":true,"description":"Report Issue ID","schema":{"type":"string"}}],"get":{"tags":["Reports"],"description":"Get possible duplicates by report ID grouped by category","operationId":"adminGetIssuePossibleDuplicates","security":[{"datahubAccount":["pruser:reports:read"]}],"responses":{"200":{"description":"A list of possible duplicate reports","content":{"application/json":{"schema":{"type":"object","required":["possible_duplicates"],"properties":{"possible_duplicates":{"type":"array","items":{"type":"object","required":["id","status","inserted_at","report_id","report_title"],"properties":{"id":{"type":"string","description":"Unique identifier for the issue"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Date when the issue was created in ISO 8601 format"},"report_id":{"type":"string","description":"ID of the report associated with the issue"},"report_title":{"type":"string","description":"Title of the report associated with the issue"},"category_id":{"type":"string","description":"Kategoria kandidata. Je vzdy zhodna s kategoriou naleza, ku ktoremu\nsa kandidati hladaju - duplicita je vztah dvoch nalezov v jednej\nkategorii, nie dvoch podnetov ako celkov.\n"},"category_name":{"type":"string"},"embedding_distance":{"type":"number","format":"float","description":"Vzdialenost embeddingov najpodobnejsej dvojice fotiek, tak ako ju\nzapisal detektor (`<->`, teda L2). Mensie je podobnejsie; chyba,\nked ju detektor nezaznamenal. Sluzi na **zoradenie** kandidatov.\n\nPercento zhody sa z nej **nepocita**. Prevod na percenta vyzaduje\nznamu skalu, a tu nemame: embeddingy pochadzaju z embed-servera\na nikde sa nenormalizuju, takze nie je overene, ci plati vztah\n`cos = 1 - d^2/2`. Keby platil, pozorovane vzdialenosti by vsetky\nvysli na 95-99 %, co by kandidatov nerozlisilo a v UI by posobilo\npresnejsie, nez aka informacia za tym je. Skutocna kosinova\npodobnost patri do `reports_possible_duplicates` ako vlastny stlpec,\nktory zapise reports-processor - dovtedy UI ukazuje vzdialenost\nv metroch a poradie.\n"},"distance_meters":{"type":"integer","description":"Vzdialenost medzi polohami oboch podnetov v metroch. Chyba, ked\naspon jedno z nich polohu nema.\n"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/issues/{issueId}/duplicate":{"x-controller-name":"reports.ctrl","parameters":[{"name":"issueId","in":"path","required":true,"description":"Report Issue ID","schema":{"type":"string"}}],"post":{"tags":["Reports"],"description":"Marks issue `duplicateId` as duplicate of `issueId`.\n\nOba nalezy musia byt v tej istej kategorii - duplicita je vztah dvoch\npodnetov v jednej kategorii, nie dvoch podnetov ako celkov.\n\nOriginal (`issueId`) smie byt v **lubovolnom** stave - duplicita je\nkonstatovanie, ze ide o tu istu vec, a to plati aj pred prijatim.\nKed je original sam duplikatom, vztah sa **skrati**: `duplicateId` sa\nzavesi rovno na koren retaze, takze v datach retaz nevznika a UI ma\nvzdy jeden aktivny original.\n\nDuplikatom (`duplicateId`) sa naopak smie stat len nalez v stave\n`open` alebo `accepted`. Vyrieseny nalez uz nie - obcan dostal finalne\nstanovisko a to sa mu neberie; presunuty ani zluceny nalez v kategorii\nuz nezije.\n\nChyby, ktore moze endpoint vratit:\n- 400: INVALID_DUPLICATE_ISSUE_STATUS (duplikat nie je `open` ani `accepted`)\n- 400: INVALID_ACTION (original vysiel po retazi na sam duplikat)\n- 400: DUPLICATE_ISSUE_CATEGORY_MISMATCH (nalezy su v roznych kategoriach)\n","operationId":"adminMarkIssueDuplicate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["duplicateId"],"properties":{"duplicateId":{"type":"string","minLength":1}}}}}},"security":[{"datahubAccount":["pruser:reports:manage"]}],"responses":{"200":{"description":"A list of possible duplicate reports","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/issues/{issueId}/decision":{"x-controller-name":"reports.ctrl","parameters":[{"name":"issueId","in":"path","required":true,"description":"Report Issue ID","schema":{"type":"string"}}],"post":{"tags":["Reports"],"description":"Rozhodnutie uradnika o naleze - **jedna transakcia**.\n\nObrazovka detailu ma v paticke jedno tlacidlo s jednym vysvetlujucim\ntextom, ktory sklada dosledky vsetkych prepinacov (\"Prijat a vyriesit +\nprekategorizovat\"). Preto je to jeden endpoint a nie tri volania: pri\nciastocnom zlyhani by nalez zostal v stave, ktory ten text slubil, ale\npouzivatel nedostal.\n\nPrilohy vyjadrenia sa nahravaju az potom, na\n`/admin/issues/{issueId}/statements/{statementId}/media` - multipart\nspolu s rozhodnutim by znamenal skalarne polia a booleany ako stringy.\n\n`new_category_ids` bez `accept` je **presun**: nalez prejde do stavu\n`moved` (u uradnika nezostava) a podnet dostane nalezy v zadanych\nkategoriach. S `accept` si ho uradnik necháva a kategorie sa len\npridavaju. Spat z `moved` vedie „znovu prijat nalez\", teda\n`PATCH /admin/reports/{reportId}/status` s `current_issue_id`.\n\nKombinacie, ktore endpoint odmietne:\n- `duplicate_of` spolu s `accept`, `resolve` alebo `statement` - nalez,\n  ktory sa stava duplikatom, preberá riesenie aj vyjadrenie originalu,\n  takze vlastne stanovisko by sa nikdy nezverejnilo,\n- `duplicates` s nalezom, ktory uz je `resolved`, `moved` alebo\n  `duplicate` - duplikatom sa smie stat len `open` alebo `accepted`,\n- prazdne telo, teda rozhodnutie, ktore nic nemeni.\n\nOriginal v `duplicate_of` smie byt v lubovolnom stave; ked je sam\nduplikatom, vztah sa skrati na koren retaze.\n\nChyby, ktore moze endpoint vratit:\n- 400: INVALID_ACTION, INVALID_ISSUE_STATUS_UPDATE, ISSUE_NOT_FOUND,\n  EXISTING_ISSUES_IN_CATEGORIES, INVALID_DUPLICATE_ISSUE_STATUS,\n  DUPLICATE_ISSUE_CATEGORY_MISMATCH\n\nKategoria, v ktorej podnet nalez uz ma (`open`, `accepted`,\n`resolved`, `duplicate`), **nie je chyba** - `new_category_ids` sa o ne\ntiho ochudobni. Vytvarat netreba nic, co uz existuje.\n\nKategoria, z ktorej nalez uz raz **presunuli** (`moved`), naopak vrati\n`EXISTING_ISSUES_IN_CATEGORIES` - je to ochrana pred slučkou. Nazad\nvedie len „znovu prijat nalez\": uradnik, ktory nalez drzi, nadiktuje\njeho identifikator kolegovi zodpovednemu za tu kategoriu a ten ho zada\nv svojom presunutom naleze.\n- 403: FORBIDDEN_ISSUE_STATE_UPDATE\n","operationId":"adminIssueDecision","security":[{"datahubAccount":["pruser:reports:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"accept":{"type":"boolean","description":"Prijat nalez - `open` prechadza na `accepted`."},"resolve":{"type":"boolean","description":"Uzavriet nalez - prechod na `resolved`. Da sa spolu\ns `accept`. Vyjadrenie sa tym uklada ako finalne a stav je\nterminalny.\n"},"new_category_ids":{"type":"array","description":"Prekategorizovanie. Zaklada nalezy v uvedenych kategoriach;\nv tejto kategorii **novy nalez nevznika**.\n","items":{"type":"string"}},"duplicate_of":{"type":"string","description":"Tento nalez sa uzavrie ako duplikat uvedeneho a preberie\njeho riesenie aj vyjadrenie. Uvedeny nalez smie byt\nv lubovolnom stave; ked je sam duplikatom, zavesi sa\ntento na jeho original.\n"},"duplicates":{"type":"array","description":"Uvedene nalezy sa uzavru ako duplikaty tohto. Smu byt len\nv stave `open` alebo `accepted`.\n","items":{"type":"string"}},"dismiss_duplicates":{"type":"boolean","description":"\"Nie su to duplikaty\" - zmaze navrhy na duplicitu tohto\nnalezu, cim `has_possible_duplicates` zhasne.\n"},"statement":{"type":"object","additionalProperties":false,"required":["text"],"properties":{"text":{"type":"string","minLength":1,"maxLength":4096}}}}}}}},"responses":{"200":{"description":"Rozhodnutie prijate","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"statement_id":{"type":"string","description":"Vytvorene vyjadrenie, ak nejake bolo v tele."}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/issues/{issueId}/statements":{"x-controller-name":"reports.ctrl","parameters":[{"name":"issueId","in":"path","required":true,"description":"Report Issue ID","schema":{"type":"string"}}],"get":{"tags":["Reports"],"description":"Vyjadrenia k nalezu, od najnovsieho.","operationId":"adminGetIssueStatements","security":[{"datahubAccount":["pruser:reports:read"]}],"responses":{"200":{"description":"Zoznam vyjadreni","content":{"application/json":{"schema":{"type":"object","required":["statements"],"properties":{"statements":{"type":"array","items":{"type":"object","description":"Vyjadrenie uradu k nalezu tak, ako ho vidi uradnik. Priebezne\n(`final: false`) alebo finalne (`final: true`) - finalne je to, ktorym\nnalez prechadza do stavu `resolved`, a viac nez jedno ich k nalezu byt\nnemoze.\n","required":["statement_id","issue_id","text","final","media","inserted_at"],"properties":{"statement_id":{"type":"string"},"issue_id":{"type":"string"},"text":{"type":"string"},"final":{"type":"boolean"},"author":{"type":"object","nullable":true,"description":"Uradnik, ktory vyjadrenie napisal. `null`, ked jeho ucet uz\nneexistuje - vyjadrenie je audit zaznam a zmazanim uctu nezanika.\nObcanovi sa autor nezobrazuje vobec, viz `PublicIssueStatement`.\n","properties":{"name":{"type":"string"},"surname":{"type":"string"}}},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/issues/{issueId}/statements/{statementId}/media":{"x-controller-name":"reports.ctrl","parameters":[{"name":"issueId","in":"path","required":true,"description":"Report Issue ID","schema":{"type":"string"}},{"name":"statementId","in":"path","required":true,"description":"Issue statement ID","schema":{"type":"string"}}],"post":{"tags":["Reports"],"description":"Prida prilohy k vyjadreniu. Vola sa hned po `decision`, ked ma\nvyjadrenie subory.\n\nChyby: 404 STATEMENT_NOT_FOUND, 403 FORBIDDEN_ISSUE_STATE_UPDATE.\n","operationId":"adminAddIssueStatementMedia","security":[{"datahubAccount":["pruser:reports:manage"]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","additionalProperties":false,"properties":{"media":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"Prilohy pridane","content":{"application/json":{"schema":{"type":"object","required":["media"],"properties":{"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/statements/{statementId}/media/{mediaId}":{"x-controller-name":"reports.ctrl","parameters":[{"name":"statementId","in":"path","required":true,"description":"Issue statement ID","schema":{"type":"string"}},{"name":"mediaId","in":"path","required":true,"description":"Media ID","schema":{"type":"string"}}],"delete":{"tags":["Reports"],"description":"Zmaze prilohu vyjadrenia - riadok aj subor.\n\nChyby: 404 STATEMENT_MEDIA_NOT_FOUND, 403 FORBIDDEN_ISSUE_STATE_UPDATE.\n","operationId":"adminDeleteIssueStatementMedia","security":[{"datahubAccount":["pruser:reports:manage"]}],"responses":{"200":{"description":"Priloha zmazana"},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/reports/{reportId}/media":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}}],"post":{"tags":["Reports"],"description":"Prida prilohy k obalke podnetu. Subory prejdu tym istym spracovanim\nako pri zalozeni podnetu (HEIC -> JPEG, varianty, EXIF poloha)\na publikuje sa MQTT sprava, aby im reports-processor dopocital\nembedding - bez neho by do detekcie duplicit nevstupili.\n\nChyby: 404 REPORTS_ITEM_NOT_FOUND, 403 REPORTS_ACCESS_FORBIDDEN.\n","operationId":"adminAddReportMedia","security":[{"datahubAccount":["pruser:reports:manage"]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","additionalProperties":false,"properties":{"media":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"Prilohy pridane","content":{"application/json":{"schema":{"type":"object","required":["media"],"properties":{"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/reports/{reportId}/media/{mediaId}":{"x-controller-name":"reports.ctrl","parameters":[{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}},{"name":"mediaId","in":"path","required":true,"description":"Media ID","schema":{"type":"string"}}],"delete":{"tags":["Reports"],"description":"Zmaze prilohu obalky - riadok aj subor.\n\nMazanie prilohy meni dokazy ohlasovatela, preto sa zaznamenava do logu\n(`adminDeleteReportMedia-deleted` s `clientAccId` a `media_id`).\n\nChyby: 404 REPORTS_MEDIA_NOT_FOUND, 403 REPORTS_ACCESS_FORBIDDEN.\n","operationId":"adminDeleteReportMedia","security":[{"datahubAccount":["pruser:reports:manage"]}],"responses":{"200":{"description":"Priloha zmazana"},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports-categories":{"x-controller-name":"reports.ctrl","get":{"tags":["Reports:Categories"],"parameters":[{"in":"query","name":"view","schema":{"type":"string","enum":["flat","tree"],"default":"flat"},"description":"`tree` vnori podkategorie do `children`. Pri neprazdnom `q` sa\n**ignoruje** a odpoved je vzdy plocha: vysledok je utrzok, v ktorom\nrodic najdenej kategorie byt nemusi, takze by sa zaradenie deti\nstratilo. Zaradenie nesie `full_path`.\n"},{"in":"query","name":"q","required":false,"schema":{"type":"string"},"description":"Hlada v ceste kategorie (`Kancelaria primatora / Komunikacia`)\na v jej identifikatore, bez ohladu na diakritiku a velkost pismen.\n\nVolajucemu s `pruser:report-categories:manage` hlada **aj v menach\nzodpovednych uradnikov**. Ostatnym nie, a nie je to kozmetika: keby\nsa podla mena dalo filtrovat aj bez toho opravnenia, dali by sa\nmena uhadnut po pismenach aj bez toho, aby ich odpoved vypisala.\n"}],"description":"Get a list of existing report categories.\n\n**Vyzaduje prihlasenie, ziadne konkretne opravnenie.** Endpoint bol do\nverzie 5.0.0 verejny, a to len historicky - nic neprihlasene ho necita.\nFormular na nahlasenie podnetu kategoriu nevybera vobec, priraduje ju\n`reports-processor`; vsetci volajuci su v `/administracia`.\n\nPreco nie rovno `pruser:report-categories:manage`: detail podnetu je za\n`pruser:reports:read` / `:manage` a potrebuje zoznam kategorii na\nprekategorizovanie nalezu, takze uradnik bez prava na spravu kategorii\nby ostal bez ponuky. Menny zoznam zodpovednych uradnikov (`users`)\na hladanie podla ich mien su preto gatovane zvlast.\n","operationId":"getReportCategories","security":[{"datahubAccount":[]}],"responses":{"200":{"description":"A list of categories","content":{"application/json":{"schema":{"type":"object","required":["report_categories"],"properties":{"report_categories":{"type":"array","items":{"allOf":[{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}},{"type":"object","properties":{"children":{"type":"array","items":{"allOf":[{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}}]}}}}]}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Reports:Categories"],"description":"Creates a new report category","operationId":"createReportCategory","security":[{"datahubAccount":["pruser:report-categories:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"`category_id` sa tu **neposiela**. Identifikator generuje server rovnako\nako pri podnetoch, nalezoch a projektoch (`generateIdentifier`), takze\nnezavisi na nazve - kategoriu je mozne premenovat a kluc na to nereaguje.\nKym to tak nebolo, skladal ho klient zo slugu nazvu.\n","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Created category","content":{"application/json":{"schema":{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports-categories/{categoryId}":{"get":{"x-controller-name":"reports.ctrl","tags":["Reports:Categories"],"description":"Get report category by ID","operationId":"getReportCategoryDetail","security":[{"optionalDatahubAccount":[]}],"parameters":[{"name":"categoryId","in":"path","required":true,"description":"Category ID","schema":{"type":"string"}}],"responses":{"200":{"description":"A single report category","content":{"application/json":{"schema":{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"delete":{"x-controller-name":"reports.ctrl","tags":["Reports:Categories"],"description":"Deletes a category based on provided ID","operationId":"deleteReportCategory","security":[{"datahubAccount":["pruser:report-categories:manage"]}],"parameters":[{"name":"categoryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted the category"},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"put":{"x-controller-name":"reports.ctrl","tags":["Reports:Categories"],"description":"Updates a report category","operationId":"updateReportCategory","security":[{"datahubAccount":["pruser:report-categories:manage"]}],"parameters":[{"name":"categoryId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"parent_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated category","content":{"application/json":{"schema":{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports-categories/{categoryId}/default":{"x-controller-name":"reports.ctrl","put":{"tags":["Reports:Categories"],"description":"Prehlasi kategoriu za predvolenu - tu, do ktorej padne podnet, ktory sa\nnepodarilo zaradit.\n\nPriznak drzi **najviac jedna** kategoria (partial unique index\n`report_categories_one_default_idx`), takze tento endpoint ho tej\ndoterajsej v tej istej transakcii odoberie. Preto nema telo: nie je co\nnastavovat, iba komu. Odobrat priznak bez toho, aby ho dostala ina\nkategoria, sa cez API neda - stav bez predvolenej kategorie vznika len\njej zmazanim a `deleteReportCategory` ho prave preto odmieta.\n\nVracia kategoriu po zmene. Ktora kategoria priznak stratila, hovori\n`previous`; je `null`, ked ziadna predvolena nebola alebo ked uz\npredvolena bola prave tato.\n","operationId":"setDefaultReportCategory","security":[{"datahubAccount":["pruser:report-categories:manage"]}],"parameters":[{"name":"categoryId","in":"path","required":true,"description":"Category ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Kategoria je predvolena","content":{"application/json":{"schema":{"type":"object","required":["category"],"properties":{"category":{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}},"previous":{"type":"object","nullable":true,"required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports-categories/{categoryId}/users":{"x-controller-name":"reports.ctrl","get":{"tags":["Reports:Categories"],"description":"Get a list of users assigned to a report category","operationId":"getReportCategoryUsers","security":[{"datahubAccount":["pruser:report-categories:users:manage"]}],"parameters":[{"name":"categoryId","in":"path","required":true,"description":"Category ID","schema":{"type":"string"}}],"responses":{"200":{"description":"List of users assigned to the category","content":{"application/json":{"schema":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"},"email":{"type":"string","description":"Kontakt uradnika. Chyba, kym sa ucet aspon raz neprihlasil - riadok\nv `digiobcan.users` zaklada az prve prihlasenie, kdezto priradenie\nku kategorii vznikne uz pri pozvani.\n"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Reports:Categories"],"description":"Priradí kategóriu zadaným používateľom.\n\nKaždá položka nesie **presne jeden** identifikátor, presne ako ho vrátilo\n`GET /users`: `client_acc_id` pre človeka, ktorý sa do aplikácie už\nprihlásil, alebo `acc_id` pre toho, kto ešte nie - tomu sa identifikátor\nv aplikácii vytvorí (`POST /app/accounts/aliases` v datahub-api). Ani\njeden alebo oba naraz znamenajú 400 `MISSING_ACCOUNT_ID`.\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: MISSING_ACCOUNT_ID\n","operationId":"addReportCategoryUsers","security":[{"datahubAccount":["pruser:report-categories:users:manage"]}],"parameters":[{"name":"categoryId","in":"path","required":true,"description":"Category ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"client_acc_id":{"type":"string"},"acc_id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["category_id","name","users"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"users":{"type":"array","description":"Priradení používatelia s identifikátorom v aplikácii. Pri\núčte, ktorý sa registroval až týmto volaním, je to jediné\nmiesto, kde sa jeho `client_acc_id` volajúci dozvie.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"},"email":{"type":"string","description":"Kontakt uradnika. Chyba, kym sa ucet aspon raz neprihlasil - riadok\nv `digiobcan.users` zaklada az prve prihlasenie, kdezto priradenie\nku kategorii vznikne uz pri pozvani.\n"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/reports-categories/{categoryId}/users/{userId}":{"x-controller-name":"reports.ctrl","delete":{"tags":["Reports:Categories"],"description":"Remove a category from a user","operationId":"deleteReportCategoryUser","security":[{"datahubAccount":["pruser:report-categories:users:manage"]}],"parameters":[{"name":"categoryId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the report category"},{"name":"userId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the user"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/users":{"x-controller-name":"users.ctrl","get":{"tags":["Users"],"description":"Vyhľadá používateľov, ktorých má zmysel priradiť ku kategórii podnetov,\nteda držiteľov úradníckych oprávnení (`pruser:reports:read`,\n`pruser:reports:manage`, `pruser:report-categories:access-all`).\nZoznam oprávnení je fixný v kóde - z requestu sa rozšíriť nedá.\n\nZoznam účtov drží datahub-api; táto služba sa doň pýta aplikačným\ntokenom, takže prehliadač úradníka žiadny token k účtom platformy\nnedrží. Vracia len identifikátor, meno a priezvisko.\n\nPoužívateľ, ktorý sa do Môjho Prešova ešte neprihlásil, tu má namiesto\n`client_acc_id` len `acc_id` - priradenie kategórie mu identifikátor\nv aplikácii dorobí samo.\n","operationId":"searchUsers","security":[{"datahubAccount":["pruser:report-categories:users:manage"]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Hľadá naprieč menom, priezviskom, e-mailom a identifikátormi účtu.\nFunguje od prvého znaku (každý token sa berie ako predpona)\na viac slov sa spája ako AND.\n"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"maximum":50,"minimum":1}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"minimum":0}}],"responses":{"200":{"description":"Zoznam kandidátov zoradený podľa priezviska a mena","content":{"application/json":{"schema":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"object","description":"Kandidát na priradenie ku kategórii podnetov.\n\nNesie **presne jeden** identifikátor: `client_acc_id`, ak sa človek do\nMôjho Prešova už niekedy prihlásil, inak `acc_id` (identifikátor účtu na\núrovni platformy). Pri priradení sa posiela ten, ktorý prišiel;\n`POST /reports-categories/{categoryId}/users` si z `acc_id` identifikátor\nv aplikácii dorobí.\n","properties":{"client_acc_id":{"type":"string"},"acc_id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/users/{userId}/reports-categories":{"x-controller-name":"users.ctrl","get":{"tags":["Users"],"description":"Get a list of categories assigned on user","operationId":"getUserReportCategories","security":[{"datahubAccount":["pruser:report-categories:users:manage"]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the user"}],"responses":{"200":{"description":"List of report categories assigned to the user","content":{"application/json":{"schema":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"object","required":["name","category_id"],"properties":{"name":{"type":"string"},"category_id":{"type":"string"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/votings":{"x-controller-name":"votings.ctrl","get":{"tags":["Votings"],"description":"Get list of public votings, sorted by open_from and voting_id, paginated by limit and pagecursor.\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: INVALID_PAGE_CURSOR\n","operationId":"getVotings","security":[{"optionalDatahubAccount":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"string"}},"description":"Array of open_from (ISO string) and voting_id to use as cursor for pagination.\nFormat: [\"2023-07-21T10:30:00.000Z\", \"voting-123\"]\n"}],"responses":{"200":{"description":"A list of votings","content":{"application/json":{"schema":{"type":"object","required":["votings"],"properties":{"votings":{"type":"array","items":{"type":"object","required":["voting_id","title","votes_count","verified_accounts_only","inserted_at","forgotten"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the voting was created in ISO 8601 format"},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"already_voted":{"type":"boolean","description":"Odovzdal volajúci účet v tomto hlasovaní hlas? Prítomné len pre prihláseného; neprihlásenému a v administračnom zozname sa nevracia. Anonymný hlas sa k účtu priradiť nedá, takže po ňom zostáva `false` - je to tá istá vlastnosť, kvôli ktorej sa anonymný hlas ani nededuplikuje."},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"allow_anonymous":{"type":"boolean","description":"If true, hlasovať smie aj neprihlásený"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/votings/{votingId}":{"x-controller-name":"votings.ctrl","get":{"tags":["Votings"],"description":"Get public voting detail by ID","operationId":"getVotingDetail","security":[{"optionalDatahubAccount":[]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"responses":{"200":{"description":"Voting detail","content":{"application/json":{"schema":{"type":"object","required":["voting_id","title","votes_count","questions","verified_accounts_only","public","available_results","available_incomplete_results"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov, `getVotingResults` vráti prázdne `questions`. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed. Má význam len pri `available_results: true`; opačná kombinácia je zakázaná CHECK-om v databáze."},"questions":{"type":"array","items":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},"description":"Pri type=scale sú to **tvrdenia**, ktoré hlasujúci hodnotí na škále,\nnie možnosti na výber.\n"}}}},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"allow_anonymous":{"type":"boolean","description":"Ak true, hlasovať smie aj neprihlásený. Pre anonymného hlasujúceho\nje `already_voted` vždy false - anonymné hlasy sa nededuplikujú.\n"},"already_voted":{"type":"boolean","description":"Whether the user has already voted in this voting"},"my_votes":{"type":"array","description":"Odpovede, ktoré tento účet v hlasovaní odovzdal - to, čo si\nhlasujúci na detaile pozrie po odhlasovaní.\n\nPríde len prihlásenému, ktorý už hlasoval, teda spolu\ns `already_voted: true`. **Anonymný hlas ho nemá** (nie je z čoho\nodvodiť kľúč) a nemá ho ani lístok odovzdaný pred migráciou 000020;\nv oboch prípadoch pole chýba celé. Chýbajúce pole preto znamená\n„nemám čo zobraziť\", nie „nevybral nič\" - prázdne pole sa\nnevracia zámerne.\n\nTvar je zhodný s `SubmitVoteRequest.votes`, aby sa dal priamo vložiť\ndo formulára v režime len na čítanie.\n","items":{"type":"object","required":["question_id","options"],"properties":{"question_id":{"type":"integer"},"options":{"type":"array","items":{"type":"object","required":["option_id"],"properties":{"option_id":{"type":"integer"},"text":{"type":"string","description":"Text otvorenej odpovede, ak ju možnosť má"},"value":{"type":"integer","description":"Hodnotenie tvrdenia pri otázke typu `scale`"}}}}}}}}}}}},"403":{"description":"You have already voted in this voting","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[403]},"name":{"enum":["VOTING_ALREADY_VOTED"]}}}]}}}},"404":{"description":"Voting not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["VOTING_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/votings/{votingId}/results":{"x-controller-name":"votings.ctrl","get":{"tags":["Votings"],"description":"Get results for a voting.\n\nPrázdne `questions` nie sú chyba, ale odpoveď „podrobnosti sa teraz nevydávajú\": buď hlasovanie ešte beží a nemá zapnuté `available_incomplete_results`, alebo má `available_results: false` a nezverejní ich nikdy. Správca hlasovaní (`pruser:votings:manage`) dostane podrobnosti vždy - obe obmedzenia platia len pre občana.","operationId":"getVotingResults","security":[{"optionalDatahubAccount":[]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"responses":{"200":{"description":"List of voting results","content":{"application/json":{"schema":{"type":"object","required":["voting_id","title","votes_count","verified_accounts_only","questions"],"properties":{"voting_id":{"type":"string","description":"Voting identifier"},"title":{"type":"string","description":"Voting title"},"description":{"type":"string","nullable":true,"description":"Optional voting description"},"open_from":{"type":"string","format":"date-time","description":"When voting opens (ISO 8601)"},"open_to":{"type":"string","format":"date-time","description":"When voting closes (ISO 8601)"},"votes_count":{"type":"integer","minimum":0,"description":"Total number of votes"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"questions":{"type":"array","items":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"allOf":[{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},{"type":"object","required":["votes_count"],"properties":{"votes_count":{"type":"integer","minimum":0,"default":0,"readOnly":true,"description":"Number of votes for this option (auto-calculated)"},"text_answers":{"type":"array","items":{"type":"string"},"description":"Array of text answers for free type options (only present when type is 'free')"},"average":{"type":"number","format":"float","nullable":true,"readOnly":true,"description":"Priemerné hodnotenie tvrdenia (len pri question.type=scale).\n`null`, keď tvrdenie nikto neohodnotil.\n"},"histogram":{"type":"array","readOnly":true,"description":"Rozdelenie hodnotení tvrdenia (len pri question.type=scale).\nVždy obsahuje všetky hodnoty scale_min..scale_max, aj tie\ns nulovým počtom.\n","items":{"type":"object","required":["value","count"],"properties":{"value":{"type":"integer","minimum":0},"count":{"type":"integer","minimum":0}}}}}}]}}}}}}}}}},"404":{"description":"Voting not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["VOTING_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/votings/{votingId}/vote":{"x-controller-name":"votings.ctrl","post":{"tags":["Votings"],"description":"Odovzdanie hlasu v hlasovaní.\n\n`votings_results` nemá stĺpec s účtom. Riadok odpovede prihláseného\nnesie `voter_key`, odtlačok odvodený z účtu kľúčom, ktorý **nie je\nv databáze** (`hmac(masterKey, client_acc_id)` ďalej cez `voting_id`,\n`question_id` a `voting.secret`) - kto získa databázu, hlas k osobe\nnepriradí, ale služba ho hlasujúcemu vie zobraziť\n(`VotingDetail.my_votes`). Je to teda anonymita voči údajom v databáze,\nnie voči prevádzkovateľovi platformy, a tak sa to má aj opisovať.\n\nPrihlásenie navyše slúži na deduplikáciu (`votings_participation` drží\n`hash(client_acc_id, voting_id, secret)`) a na gamifikáciu.\n\n**Anonymný hlas `voter_key` nedostane** - nie je z čoho ho odvodiť -\ntakže si ho hlasujúci ani nepozrie.\n\nKto smie hlasovať, určuje samotné hlasovanie:\n- `allow_anonymous: true` - smie ktokoľvek; neprihlásený musí poslať\n  `recaptchaToken`. Takýto hlas sa **nededuplikuje** a nedostáva body.\n- `verified_accounts_only: true` - len prihlásený s overeným účtom.\n- inak - akýkoľvek prihlásený.\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: VOTING_INACTIVE, INVALID_QUESTIONS, DUPLICATE_OPTIONS, INSUFFICIENT_OPTIONS, MISSING_REQUIRED_STATEMENTS, TOO_MANY_OPTIONS, INVALID_OPTIONS, INVALID_SCALE_VALUE, SCALE_TEXT_NOT_ALLOWED, VALUE_NOT_ALLOWED\n- 401: LOGIN_REQUIRED\n- 403: VERIFIED_ACCOUNT_REQUIRED, RECAPTCHA_VERIFICATION_FAILED\n- 404: VOTING_NOT_FOUND\n- 409: VOTING_ALREADY_VOTED\n- 410: VOTING_FORGOTTEN\n","operationId":"submitVote","security":[{"optionalDatahubAccount":[]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["votes"],"properties":{"votes":{"type":"array","minItems":1,"items":{"type":"object","required":["question_id","options"],"properties":{"question_id":{"type":"integer"},"options":{"type":"array","minItems":1,"items":{"type":"object","required":["option_id"],"properties":{"option_id":{"type":"integer"},"text":{"type":"string","maxLength":4096},"value":{"type":"integer","minimum":0,"maximum":10,"description":"Hodnotenie tvrdenia na škále. Povinné pre otázku\ntype=scale, zakázané pre ostatné typy. Škálová odpoveď\ncestuje ako jedna položka `options` na jedno tvrdenie.\n\nDolná hranica je 0, lebo škála smie začínať nulou\n(`scale_min`); že hodnota patrí do rozsahu **tejto**\notázky, kontroluje server.\n"}}}}}}},"recaptchaToken":{"type":"string","description":"reCAPTCHA v3 token. Povinný, keď hlasujúci nie je prihlásený\n(hlasovanie musí mať `allow_anonymous: true`).\n"}}}}}},"responses":{"200":{"description":"Vote submitted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/votings":{"x-controller-name":"votings.ctrl","get":{"tags":["Votings"],"description":"Get list of all votings, sorted by open_from and voting_id, paginated by limit and pagecursor.\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: INVALID_PAGE_CURSOR\n","operationId":"adminGetVotings","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"string"}},"description":"Array of open_from (ISO string) and voting_id to use as cursor for pagination.\nFormat: [\"2023-07-21T10:30:00.000Z\", \"voting-123\"]\n"}],"responses":{"200":{"description":"A list of votings","content":{"application/json":{"schema":{"type":"object","required":["votings"],"properties":{"votings":{"type":"array","items":{"type":"object","required":["voting_id","title","votes_count","verified_accounts_only","inserted_at","forgotten"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the voting was created in ISO 8601 format"},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"already_voted":{"type":"boolean","description":"Odovzdal volajúci účet v tomto hlasovaní hlas? Prítomné len pre prihláseného; neprihlásenému a v administračnom zozname sa nevracia. Anonymný hlas sa k účtu priradiť nedá, takže po ňom zostáva `false` - je to tá istá vlastnosť, kvôli ktorej sa anonymný hlas ani nededuplikuje."},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"allow_anonymous":{"type":"boolean","description":"If true, hlasovať smie aj neprihlásený"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Votings"],"description":"Create a new voting\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: VOTING_INVALID_DATES, VOTING_INVALID_END_DATE, VOTING_INVALID_AUDIENCE, VOTING_INVALID_OPTIONS_RANGE, VOTING_INSUFFICIENT_OPTIONS, INVALID_OPTION_URL, VOTING_INVALID_SCALE, VOTING_INVALID_SCALE_MIN, VOTING_SCALE_NOT_ALLOWED, VOTING_SCALE_NO_STATEMENTS, VOTING_SCALE_FREE_OPTION, VOTING_REQUIRED_NOT_ALLOWED\n- 500: VOTING_CREATION_FAILED\n","operationId":"adminCreateVoting","security":[{"datahubAccount":["pruser:votings:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","questions","verified_accounts_only","public","available_incomplete_results"],"properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Title of the voting"},"description":{"type":"string","minLength":1,"maxLength":4096,"nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","nullable":true,"description":"When the voting opens (defaults to current time if not provided)"},"open_to":{"type":"string","format":"date-time","nullable":true,"description":"When the voting closes"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"allow_anonymous":{"type":"boolean","default":false,"description":"Ak true, hlasovať smie aj neprihlásený (vyžaduje sa reCAPTCHA).\nNedá sa kombinovať s `verified_accounts_only`. Anonymné hlasy sa\n**nededuplikujú** - bez účtu nie je z čoho vyrobiť hash účastníka.\n"},"available_results":{"type":"boolean","default":true,"description":"Sprístupniť občanovi výsledky? `false` ich skryje natrvalo - ani po uzavretí sa nezverejnia. Nepovinné a predvolene `true`, aby klient, ktorý o tomto rozhodnutí nevie, vytvoril hlasovanie s doterajším správaním. Pri `false` server zároveň vynúti `available_incomplete_results: false`."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed"},"questions":{"type":"array","minItems":1,"description":"Questions for the voting","items":{"type":"object","required":["title","min_options","max_options","options"],"properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Question title"},"description":{"type":"string","minLength":1,"maxLength":2048,"nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. Zámerne nie je povinný - keď chýba, server ho\ndopočíta z tvaru otázky (tá istá derivácia ako backfill\nv migrácii 000019), takže starý klient ďalej validuje.\nPri `scale` je `options` zoznam tvrdení, `scale_max` je\npovinný, `max_options` server prepíše na počet tvrdení\na `min_options` na počet tých, ktoré sú `required`. Pri\n`free_text` a `single_choice` server prepíše\n`min_options`/`max_options` na 1.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"description":"Dolná hranica škály (len pre type=scale, inak zakázané).\nKeď chýba, je to `1`. `0` dá stupnicu, kde je nula\nplnohodnotná odpoveď („projekt nechcem podporiť\"), nie\nchýbajúce hodnotenie.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"description":"Horná hranica škály. Povinné pre type=scale, inak zakázané."},"scale_min_label":{"type":"string","maxLength":64,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","maxLength":64,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","minItems":1,"items":{"type":"object","required":["title","type"],"properties":{"title":{"type":"string","maxLength":255,"description":"Option text/title"},"description":{"type":"string","maxLength":2048,"description":"Nepovinný popis tvrdenia - pri hlasovaní o projektoch\nzámer projektu. Zobrazuje sa pod názvom tvrdenia.\n"},"required":{"type":"boolean","description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok\nodovzdať? Keď chýba, je to `true`. Prípustné **len pri type=scale**; pri\nostatných typoch je 400 (`VOTING_REQUIRED_NOT_ALLOWED`),\nlebo počet vybraných možností riadia\n`min_options`/`max_options`. Škála, ktorej sú všetky\ntvrdenia nepovinné, sa smie preskočiť celá - taká\notázka do `votes` vôbec nepríde.\n"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"},"url":{"type":"string","format":"uri","description":"Optional url for the option"}}}}}}}}}}}},"responses":{"201":{"description":"Voting created successfully","content":{"application/json":{"schema":{"type":"object","required":["voting_id"],"properties":{"voting_id":{"type":"string","description":"ID of the created voting"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/votings/{votingId}":{"x-controller-name":"votings.ctrl","get":{"tags":["Votings"],"description":"Get voting detail by ID\n\nChyby, ktoré môže endpoint vrátiť:\n- 404: VOTING_NOT_FOUND\n","operationId":"adminGetVotingDetail","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"responses":{"200":{"description":"Voting detail","content":{"application/json":{"schema":{"type":"object","required":["voting_id","title","votes_count","questions","verified_accounts_only","public","available_results","available_incomplete_results"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov, `getVotingResults` vráti prázdne `questions`. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed. Má význam len pri `available_results: true`; opačná kombinácia je zakázaná CHECK-om v databáze."},"questions":{"type":"array","items":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},"description":"Pri type=scale sú to **tvrdenia**, ktoré hlasujúci hodnotí na škále,\nnie možnosti na výber.\n"}}}},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"allow_anonymous":{"type":"boolean","description":"Ak true, hlasovať smie aj neprihlásený. Pre anonymného hlasujúceho\nje `already_voted` vždy false - anonymné hlasy sa nededuplikujú.\n"},"already_voted":{"type":"boolean","description":"Whether the user has already voted in this voting"},"my_votes":{"type":"array","description":"Odpovede, ktoré tento účet v hlasovaní odovzdal - to, čo si\nhlasujúci na detaile pozrie po odhlasovaní.\n\nPríde len prihlásenému, ktorý už hlasoval, teda spolu\ns `already_voted: true`. **Anonymný hlas ho nemá** (nie je z čoho\nodvodiť kľúč) a nemá ho ani lístok odovzdaný pred migráciou 000020;\nv oboch prípadoch pole chýba celé. Chýbajúce pole preto znamená\n„nemám čo zobraziť\", nie „nevybral nič\" - prázdne pole sa\nnevracia zámerne.\n\nTvar je zhodný s `SubmitVoteRequest.votes`, aby sa dal priamo vložiť\ndo formulára v režime len na čítanie.\n","items":{"type":"object","required":["question_id","options"],"properties":{"question_id":{"type":"integer"},"options":{"type":"array","items":{"type":"object","required":["option_id"],"properties":{"option_id":{"type":"integer"},"text":{"type":"string","description":"Text otvorenej odpovede, ak ju možnosť má"},"value":{"type":"integer","description":"Hodnotenie tvrdenia pri otázke typu `scale`"}}}}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"put":{"tags":["Votings"],"description":"Update voting\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: VOTING_ALREADY_ACTIVE, VOTING_INVALID_DATES, VOTING_INVALID_AUDIENCE, VOTING_INVALID_OPTIONS_RANGE, VOTING_INSUFFICIENT_OPTIONS, INVALID_OPTION_URL, VOTING_INVALID_SCALE, VOTING_INVALID_SCALE_MIN, VOTING_SCALE_NOT_ALLOWED, VOTING_SCALE_NO_STATEMENTS, VOTING_SCALE_FREE_OPTION, VOTING_REQUIRED_NOT_ALLOWED, VOTING_UPDATE_FAILED\n- 404: VOTING_NOT_FOUND\n","operationId":"adminUpdateVoting","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","questions","verified_accounts_only","public","available_incomplete_results"],"properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Title of the voting"},"description":{"type":"string","minLength":1,"maxLength":4096,"nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","nullable":true,"description":"When the voting opens (defaults to current time if not provided)"},"open_to":{"type":"string","format":"date-time","nullable":true,"description":"When the voting closes"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"allow_anonymous":{"type":"boolean","default":false,"description":"Ak true, hlasovať smie aj neprihlásený (vyžaduje sa reCAPTCHA).\nNedá sa kombinovať s `verified_accounts_only`. Anonymné hlasy sa\n**nededuplikujú** - bez účtu nie je z čoho vyrobiť hash účastníka.\n"},"available_results":{"type":"boolean","default":true,"description":"Sprístupniť občanovi výsledky? `false` ich skryje natrvalo - ani po uzavretí sa nezverejnia. Nepovinné a predvolene `true`, aby klient, ktorý o tomto rozhodnutí nevie, vytvoril hlasovanie s doterajším správaním. Pri `false` server zároveň vynúti `available_incomplete_results: false`."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed"},"questions":{"type":"array","minItems":1,"description":"Questions for the voting","items":{"type":"object","required":["title","min_options","max_options","options"],"properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Question title"},"description":{"type":"string","minLength":1,"maxLength":2048,"nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. Zámerne nie je povinný - keď chýba, server ho\ndopočíta z tvaru otázky (tá istá derivácia ako backfill\nv migrácii 000019), takže starý klient ďalej validuje.\nPri `scale` je `options` zoznam tvrdení, `scale_max` je\npovinný, `max_options` server prepíše na počet tvrdení\na `min_options` na počet tých, ktoré sú `required`. Pri\n`free_text` a `single_choice` server prepíše\n`min_options`/`max_options` na 1.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"description":"Dolná hranica škály (len pre type=scale, inak zakázané).\nKeď chýba, je to `1`. `0` dá stupnicu, kde je nula\nplnohodnotná odpoveď („projekt nechcem podporiť\"), nie\nchýbajúce hodnotenie.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"description":"Horná hranica škály. Povinné pre type=scale, inak zakázané."},"scale_min_label":{"type":"string","maxLength":64,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","maxLength":64,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","minItems":1,"items":{"type":"object","required":["title","type"],"properties":{"title":{"type":"string","maxLength":255,"description":"Option text/title"},"description":{"type":"string","maxLength":2048,"description":"Nepovinný popis tvrdenia - pri hlasovaní o projektoch\nzámer projektu. Zobrazuje sa pod názvom tvrdenia.\n"},"required":{"type":"boolean","description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok\nodovzdať? Keď chýba, je to `true`. Prípustné **len pri type=scale**; pri\nostatných typoch je 400 (`VOTING_REQUIRED_NOT_ALLOWED`),\nlebo počet vybraných možností riadia\n`min_options`/`max_options`. Škála, ktorej sú všetky\ntvrdenia nepovinné, sa smie preskočiť celá - taká\notázka do `votes` vôbec nepríde.\n"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"},"url":{"type":"string","format":"uri","description":"Optional url for the option"}}}}}}}}}}}},"responses":{"200":{"description":"Voting updated successfully","content":{"application/json":{"schema":{"type":"object","required":["voting_id","title","votes_count","questions","verified_accounts_only","public","available_results","available_incomplete_results"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov, `getVotingResults` vráti prázdne `questions`. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed. Má význam len pri `available_results: true`; opačná kombinácia je zakázaná CHECK-om v databáze."},"questions":{"type":"array","items":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},"description":"Pri type=scale sú to **tvrdenia**, ktoré hlasujúci hodnotí na škále,\nnie možnosti na výber.\n"}}}},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"allow_anonymous":{"type":"boolean","description":"Ak true, hlasovať smie aj neprihlásený. Pre anonymného hlasujúceho\nje `already_voted` vždy false - anonymné hlasy sa nededuplikujú.\n"},"already_voted":{"type":"boolean","description":"Whether the user has already voted in this voting"},"my_votes":{"type":"array","description":"Odpovede, ktoré tento účet v hlasovaní odovzdal - to, čo si\nhlasujúci na detaile pozrie po odhlasovaní.\n\nPríde len prihlásenému, ktorý už hlasoval, teda spolu\ns `already_voted: true`. **Anonymný hlas ho nemá** (nie je z čoho\nodvodiť kľúč) a nemá ho ani lístok odovzdaný pred migráciou 000020;\nv oboch prípadoch pole chýba celé. Chýbajúce pole preto znamená\n„nemám čo zobraziť\", nie „nevybral nič\" - prázdne pole sa\nnevracia zámerne.\n\nTvar je zhodný s `SubmitVoteRequest.votes`, aby sa dal priamo vložiť\ndo formulára v režime len na čítanie.\n","items":{"type":"object","required":["question_id","options"],"properties":{"question_id":{"type":"integer"},"options":{"type":"array","items":{"type":"object","required":["option_id"],"properties":{"option_id":{"type":"integer"},"text":{"type":"string","description":"Text otvorenej odpovede, ak ju možnosť má"},"value":{"type":"integer","description":"Hodnotenie tvrdenia pri otázke typu `scale`"}}}}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"patch":{"tags":["Votings"],"description":"Update voting status (open/close)\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: VOTING_INVALID_STATUS_UPDATE, VOTING_INACTIVE, VOTING_NOT_FOUND\n","operationId":"adminUpdateVotingStatus","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["status"],"properties":{"status":{"type":"string","enum":["open","closed"]}}}}}},"responses":{"200":{"description":"Voting status updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"Voting status updated successfully"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"delete":{"tags":["Votings"],"description":"Archivovanie hlasovania (GDPR).\n\nZmaže `votings.secret`, všetky záznamy o účasti a `voter_key` spolu\ns voľnými odpoveďami (`votings_results.text`). Dôsledky, ktoré treba\npovedať pred stlačením: hlasovanie zmizne občanom zo zoznamu aj\nz detailu, **hlasujúci si svoje odpovede už nepozrú** a voľné odpovede\nsú nenávratne zmazané. Agregované výsledky (počty, histogramy škál)\nzostávajú.\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: VOTING_ALREADY_FORGOTTEN\n- 404: VOTING_NOT_FOUND\n","operationId":"adminForgetVoting","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"responses":{"200":{"description":"Voting forgotten successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/votings/{votingId}/visibility":{"x-controller-name":"votings.ctrl","patch":{"tags":["Votings"],"description":"Viditeľnosť hlasovania pre občana: či detail vidia aj neprihlásení\n(`public`) a či a kedy sa zverejňujú podrobné výsledky\n(`available_results`, `available_incomplete_results`).\n\n**Vlastný endpoint, lebo `PUT /admin/votings/{votingId}` sa po otvorení\nhlasovania odmieta** (`VOTING_ALREADY_ACTIVE`) - a to je práve stav,\nv ktorom sa mesto o zverejnení výsledkov rozhoduje. Obsah hlasovania\n(otázky, dátumy, publikum) tento endpoint nemení; mení len to, čo z už\nodovzdaných hlasov smie občan vidieť.\n\nPosielať sa dá aj jeden kľúč - neuvedené zostávajú, ako boli.\n`available_results: false` strhne so sebou aj\n`available_incomplete_results` (priebežné výsledky nezverejneného\nhlasovania nedávajú zmysel a `CHECK` v databáze ich nepustí).\nKombinácia „nezverejňovať, ale priebežne áno\" poslaná naraz je chyba,\nnie tichá oprava.\n\nArchivované (zabudnuté) hlasovanie sa prepnúť nedá - jeho podrobné\nvýsledky sa nezobrazujú tak či tak.\n\nChyby, ktoré môže endpoint vrátiť:\n- 400: VOTING_INVALID_RESULTS_VISIBILITY, VOTING_ALREADY_FORGOTTEN\n- 404: VOTING_NOT_FOUND\n","operationId":"adminUpdateVotingVisibility","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"public":{"type":"boolean","description":"Detail hlasovania vidia aj neprihlásení."},"available_results":{"type":"boolean","description":"Občan podrobné výsledky uvidí (po uzavretí)."},"available_incomplete_results":{"type":"boolean","description":"Občan vidí podrobné výsledky už počas hlasovania. Má význam len pri `available_results: true`."}}}}}},"responses":{"200":{"description":"Voting visibility updated successfully","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["public","available_results","available_incomplete_results"],"properties":{"public":{"type":"boolean"},"available_results":{"type":"boolean"},"available_incomplete_results":{"type":"boolean"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/votings/{votingId}/participants/{clientAccId}":{"x-controller-name":"votings.ctrl","delete":{"tags":["Votings"],"description":"Zabudnutie hlasu jedného človeka (GDPR, čl. 17).\n\nMaže **aj samotné odpovede**, nie len záznam o účasti. Predtým to\nnešlo - `votings_results` nemal ako riadky priradiť - a endpoint tak\nvedel odstrániť len väzbu, čo žiadosti o výmaz obsahu hlasu nevyhovelo.\nOdpovede sa nájdu cez `voter_key`, ktorý sa odvádza z `clientAccId`;\npreto sa v ceste **od verzie 6.0.0 posiela ID účtu, nie hash účasti**.\nZ hashu sa kľúč odvodiť nedá a volajúci ID účtu aj tak musel mať, aby si\nhash vôbec vyrobil.\n\nČo endpoint nezmaže: anonymné hlasy (nemajú `voter_key`, takže sa\nnedajú priradiť nikomu) a lístky odovzdané pred migráciou 000020.\n\nZmazaním záznamu o účasti zaniká aj deduplikačná zábrana, takže ten\nčlovek v hlasovaní môže hlasovať znova. Je to zámerné - po výmaze hlas\nnemá - ale treba o tom vedieť.\n\nChyby, ktoré môže endpoint vrátiť:\n- 404: VOTING_NOT_FOUND, PARTICIPATION_NOT_FOUND\n- 410: VOTING_FORGOTTEN\n","operationId":"adminForgetUserVote","security":[{"datahubAccount":["pruser:votings:manage"]}],"parameters":[{"name":"votingId","in":"path","required":true,"schema":{"type":"string"},"description":"ID of the voting"},{"name":"clientAccId","in":"path","required":true,"schema":{"type":"string"},"description":"ID účtu, ktorého hlas sa má zabudnúť"}],"responses":{"200":{"description":"User vote forgotten successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/projects":{"x-controller-name":"projects.ctrl","get":{"tags":["Projects"],"description":"List all projects as an admin","operationId":"adminGetProjects","security":[{"datahubAccount":["pruser:projects:manage"]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},{"name":"pagecursor","in":"query","required":false,"style":"form","explode":true,"schema":{"type":"array","minItems":2,"maxItems":2,"items":{"type":"string"}},"description":"Array of open_from (ISO string) and project_id to use as cursor for pagination.\nFormat: [\"2023-07-21T10:30:00.000Z\", \"voting-123\"]\n"}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"type":"object","required":["projects"],"properties":{"projects":{"type":"array","items":{"type":"object","required":["project_id","title","inserted_at"],"properties":{"project_id":{"type":"string"},"title":{"type":"string"},"inserted_at":{"type":"string","format":"date-time"}}}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"post":{"tags":["Projects"],"description":"Create a new project","operationId":"adminCreateProject","security":[{"datahubAccount":["pruser:projects:manage"]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","required":["title","description"],"properties":{"title":{"type":"string","minLength":1,"maxLength":256},"description":{"type":"string","maxLength":2048},"media":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"Project successfully created","content":{"application/json":{"schema":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"string"}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/projects/{projectId}":{"x-controller-name":"projects.ctrl","parameters":[{"name":"projectId","in":"path","required":true,"description":"Project ID","schema":{"type":"string"}}],"get":{"tags":["Projects"],"description":"Get project detail as an admin","operationId":"adminGetProjectDetail","security":[{"datahubAccount":["pruser:projects:manage"]}],"responses":{"200":{"description":"Project detail","content":{"application/json":{"schema":{"type":"object","required":["project_id","title","description","media","inserted_at"],"properties":{"project_id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["PROJECT_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"patch":{"tags":["Projects"],"description":"Update project detail","operationId":"adminUpdateProject","security":[{"datahubAccount":["pruser:projects:manage"]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":256},"description":{"type":"string","maxLength":2048},"media":{"description":"New media to add","type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"Project successfully updated"},"404":{"description":"Project not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["PROJECT_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}},"delete":{"tags":["Projects"],"description":"Delete project","operationId":"adminDeleteProject","security":[{"datahubAccount":["pruser:projects:manage"]}],"responses":{"200":{"description":"Project successfully deleted"},"404":{"description":"Project not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["PROJECT_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/admin/projects/{projectId}/media/{mediaId}":{"x-controller-name":"projects.ctrl","parameters":[{"name":"projectId","in":"path","required":true,"description":"Project ID","schema":{"type":"string"}},{"name":"mediaId","in":"path","required":true,"description":"Media ID","schema":{"type":"string"}}],"delete":{"tags":["Projects"],"description":"Delete project media","operationId":"adminDeleteProjectMedia","security":[{"datahubAccount":["pruser:projects:manage"]}],"responses":{"200":{"description":"Media successfully deleted"},"404":{"description":"Media not found","content":{"application/json":{"schema":{"allOf":[{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},{"type":"object","properties":{"statusCode":{"enum":[404]},"name":{"enum":["PROJECT_MEDIA_NOT_FOUND"]}}}]}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/geo/boundary":{"x-controller-name":"geo.ctrl","get":{"tags":["Geo"],"description":"Hranica mesta Prešov ako GeoJSON polygón vo WGS84 (EPSG:4326).\n\nVerejné a bez tokenu - je to statická referenčná geometria, z ktorej si\nfrontend kreslí masku na mape a predbežne overuje polohu podnetu ešte\npred odoslaním. Server podľa toho istého polygónu rozhoduje aj v\n`POST /me/reports`, takže sa mapa a API nemôžu rozísť v tom, čo je\n\"na území mesta\".\n\nPolygón je hranica mesta rozšírená o ~100 m von, aby podnet na ceste,\nktorá sama tvorí hranicu, neskončil na 400.\n","operationId":"getCityBoundary","responses":{"200":{"description":"GeoJSON polygón hranice mesta","content":{"application/json":{"schema":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Polygon"]},"coordinates":{"description":"Prstence polygónu, každý ako pole dvojíc [lon, lat].","type":"array","items":{}}}}}}},"default":{"description":"Error","content":{"application/json":{"schema":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}}}}}}}},"/docs":{"description":"Docs"}},"components":{"schemas":{"Error":{"required":["name","statusCode"],"type":"object","properties":{"statusCode":{"type":"integer"},"name":{"type":"string"},"userinfo":{"type":"string","description":"Localized info"}}},"News":{"required":["id"],"type":"object","properties":{"id":{"type":"string"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"title":{"type":"string"},"description":{"type":"string"},"image":{"type":"string","description":"URL to the image"},"date":{"type":"string","format":"date-time","description":"Date of the news in ISO 8601 format"},"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"},"categories":{"type":"array","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}},"WebPushSubscription":{"type":"object","required":["endpoint","keys"],"properties":{"endpoint":{"type":"string","description":"URL to the push service endpoint"},"keys":{"type":"object","required":["p256dh","auth"],"properties":{"p256dh":{"type":"string","description":"Base64 encoded public key"},"auth":{"type":"string","description":"Base64 encoded authentication secret"}}}}},"UserNotificationSettings":{"type":"object","required":["enabled","interval"],"properties":{"enabled":{"type":"boolean","description":"Whether notifications are enabled"},"interval":{"type":"string","enum":["daily","weekly","monthly"],"nullable":true,"description":"Notification frequency"}}},"Subscription":{"type":"object","required":["category_id","subscribed"],"properties":{"category_id":{"type":"string"},"subscribed":{"type":"boolean"}}},"Notification":{"type":"object","required":["tag","title","sent_at"],"properties":{"tag":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"url":{"type":"string","format":"uri"},"sent_at":{"type":"string","format":"date-time","description":"Date of the notification in ISO 8601 format"},"icon":{"type":"string","description":"URL to the icon"},"inserted_at":{"type":"string","format":"date-time","description":"Inserted date in ISO 8601 format"},"read_at":{"type":"string","format":"date-time","description":"Date when the notification was read in ISO 8601 format"}}},"NewsCategory":{"type":"object","required":["category_id","name"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}},"NewNewsCategory":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}},"UpdateNewsCategory":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"parent_id":{"type":"string"}}},"AdminReportListIssue":{"type":"object","description":"Nalez (issue) podnetu - podnet v konkretnej kategorii - tak, ako ho\nvidi prihlaseny admin v zozname podnetov.\n","required":["issue_id","category_id","status","inserted_at"],"properties":{"issue_id":{"type":"string","description":"Identifikator nalezu"},"category_id":{"type":"string","description":"Kategoria, v ktorej je podnet vedeny"},"category_name":{"type":"string","description":"Nazov kategorie"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Datum zaradenia podnetu do kategorie"},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates`, nie zo stavu - `possible_duplicate`\nako stav zanikol. Priznak zhasne, ked uradnik navrhy zamietne\n(`dismiss_duplicates`) alebo ked sa nalez stane duplikatom.\n"}}},"AdminReportListItem":{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Riadok zoznamu podnetov pre admina - jeden podnet, nie jeden\nnalez. `status` je stav celeho podnetu derivovany zo stavov\nnalezov v `issues`: vyhrava najmenej pokrocily stav, aby riadok\nvzdy priznal, ze podnet este nieco potrebuje\n(`open` > `accepted` > `duplicate` > `resolved`). Podnet je teda\n`resolved` az vtedy, ked je vyrieseny kazdy pristupny nalez.\nBez `issues` je nedefinovany.\n","properties":{"issue_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - riadok je podnet,\nktore moze mat viac nalezov. Zoznam nalezov je v `issues`.\n"},"category_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - kategorie podnetu\nsu v `issues`.\n"},"issues":{"type":"array","description":"Nalezy podnetu, ktore ma prihlaseny admin pravo vidiet -\nsuperadmin (`pruser:report-categories:access-all`) vsetky,\nostatni len tie vo svojich kategoriach. Presunute (`moved`)\nnalezy v zozname nie su, rovnako ako v tabulke nalezov v detaile.\nRiadok zoznamu je jeden podnet, nie jeden nalez.\nDetail podnetu toto pole nevracia - ma na nalezy vlastny\nendpoint `/admin/reports/{reportId}/issues`.\n","items":{"type":"object","description":"Nalez (issue) podnetu - podnet v konkretnej kategorii - tak, ako ho\nvidi prihlaseny admin v zozname podnetov.\n","required":["issue_id","category_id","status","inserted_at"],"properties":{"issue_id":{"type":"string","description":"Identifikator nalezu"},"category_id":{"type":"string","description":"Kategoria, v ktorej je podnet vedeny"},"category_name":{"type":"string","description":"Nazov kategorie"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Datum zaradenia podnetu do kategorie"},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates`, nie zo stavu - `possible_duplicate`\nako stav zanikol. Priznak zhasne, ked uradnik navrhy zamietne\n(`dismiss_duplicates`) alebo ked sa nalez stane duplikatom.\n"}}}},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and\nnot expired. Votes have no type and no weight, so this is the whole\nstory: one citizen's vote is one.\n"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"submitted_at":{"type":"string","format":"date-time","description":"Datum podania podnetu obcanom (digiobcan.reports.inserted_at).\nV zozname pre admina je totozny s `inserted_at` - riadok je cele\npodnet, takze aj `inserted_at` je datum jeho podania, nie\ndatum vzniku nalezu (ten je na kazdom prvku `issues`).\n`deadline_at` sa pocita z tohto pola.\n"},"deadline_at":{"type":"string","format":"date-time","description":"Lehota na vyjadrenie - datum podania podnetu\n(submitted_at) + N kalendarnych dni.\nN je konfigurovatelne cez `reports.responseDeadlineDays`.\n"},"overdue":{"type":"boolean","description":"true, ak lehota na vyjadrenie uz uplynula a aspon jeden\nz pristupnych nalezov podnetu je stale nepridelen[y]\n(status `open`). Lehota bezi po **prijatie** nalezu, nie po\njeho vyriesenie. Rovnako to plati v zozname aj v detaile.\n"}}}]},"ReportListItem":{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},"MyReportListItem":{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Riadok zoznamu vlastnych podnetov. Jeden **podnet**, nie jeden nalez.\n\n`status` je preto derivovany zo stavov vsetkych jeho nalezov, presne\nako na `ReportDetail` a `AdminReportListItem`: podnet je `resolved`\naz vtedy, ked je vyrieseny **kazdy** jeho nalez. Bez neho sa\nv zozname nedalo rozlisit vyrieseny podnet od podaneho - `accepted`\nje pri vyriesenom `false`, takze taky podnet hlasil obcanovi\n„Podane\" aj mesiac po tom, co ho mesto uzavrelo.\n\n`accepted` zostava, aby starsi frontend nezostal bez stavu vobec.\n","additionalProperties":false,"required":["accepted"],"properties":{"description":{"type":"string","description":"Description of the report"},"accepted":{"type":"boolean"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"distance":{"type":"number","description":"Distance from the provided location in meters (only present when location parameter is used)"}}}]},"ReportDetail":{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Detail podnetu pre obcana - jeden **podnet**, nie jeden nalez.\n\nPreto je tu `status` **derivovany zo stavov vsetkych jeho nalezov**:\nvyhrava najmenej pokrocily (`open` > `accepted` > `duplicate` >\n`resolved`), presne ako na `AdminReportListItem`. Podnet je teda\n`resolved` az vtedy, ked je vyrieseny **kazdy** jeho nalez.\nPresunute (`moved`) nalezy do derivacie nevstupuju; podnet, ktory\nma len take, stav nema. Riadok `GET /reports` je oproti tomu jeden\nnalez, takze tam to iste pole nesie stav toho jedneho nalezu.\n\nBez `status` sa uzavretost podnetu z verejneho API odvodit neda:\n`/reports/{reportId}/status` nesie len nalezy, ktore sa uz rozhybali\n(`accepted`, `duplicate`, `resolved`), takze nalez v stave `open`\nv nej krok vobec nema.\n","properties":{"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"description":{"type":"string"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]}}}]},"AdminReportDetail":{"allOf":[{"allOf":[{"type":"object","required":["id","title","inserted_at","media"],"properties":{"id":{"type":"string","description":"Unique identifier for the report"},"issue_id":{"type":"string","description":"Identifier of the issue"},"title":{"type":"string","description":"Title of the report"},"category_id":{"type":"string","description":"Identifier of the issue's category the report belongs to"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the report was created in ISO 8601 format"},"processed_at":{"type":"string","format":"date-time","description":"Date when the report was processed in ISO 8601 format"},"description":{"type":"string","description":"Description of the report"},"media":{"type":"array","items":{"type":"object","required":["public_url","filename","media_type"],"properties":{"media_id":{"type":"string","format":"uuid","description":"Identifikator prilohy. Bez neho sa priloha neda adresovat, teda\nani zmazat cez `DELETE /admin/reports/{reportId}/media/{mediaId}`.\n"},"filename":{"type":"string"},"public_url":{"type":"string"},"media_type":{"type":"string"}}}},"explicit":{"type":"boolean"},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and not\nexpired. Votes have no type and no weight.\n"}}},{"type":"object","description":"Riadok zoznamu podnetov pre admina - jeden podnet, nie jeden\nnalez. `status` je stav celeho podnetu derivovany zo stavov\nnalezov v `issues`: vyhrava najmenej pokrocily stav, aby riadok\nvzdy priznal, ze podnet este nieco potrebuje\n(`open` > `accepted` > `duplicate` > `resolved`). Podnet je teda\n`resolved` az vtedy, ked je vyrieseny kazdy pristupny nalez.\nBez `issues` je nedefinovany.\n","properties":{"issue_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - riadok je podnet,\nktore moze mat viac nalezov. Zoznam nalezov je v `issues`.\n"},"category_id":{"type":"string","deprecated":true,"description":"V zozname podnetov pre admina sa nevraca - kategorie podnetu\nsu v `issues`.\n"},"issues":{"type":"array","description":"Nalezy podnetu, ktore ma prihlaseny admin pravo vidiet -\nsuperadmin (`pruser:report-categories:access-all`) vsetky,\nostatni len tie vo svojich kategoriach. Presunute (`moved`)\nnalezy v zozname nie su, rovnako ako v tabulke nalezov v detaile.\nRiadok zoznamu je jeden podnet, nie jeden nalez.\nDetail podnetu toto pole nevracia - ma na nalezy vlastny\nendpoint `/admin/reports/{reportId}/issues`.\n","items":{"type":"object","description":"Nalez (issue) podnetu - podnet v konkretnej kategorii - tak, ako ho\nvidi prihlaseny admin v zozname podnetov.\n","required":["issue_id","category_id","status","inserted_at"],"properties":{"issue_id":{"type":"string","description":"Identifikator nalezu"},"category_id":{"type":"string","description":"Kategoria, v ktorej je podnet vedeny"},"category_name":{"type":"string","description":"Nazov kategorie"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Datum zaradenia podnetu do kategorie"},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates`, nie zo stavu - `possible_duplicate`\nako stav zanikol. Priznak zhasne, ked uradnik navrhy zamietne\n(`dismiss_duplicates`) alebo ked sa nalez stane duplikatom.\n"}}}},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"votes_count":{"type":"integer","description":"Number of votes on the report that still count - not revoked and\nnot expired. Votes have no type and no weight, so this is the whole\nstory: one citizen's vote is one.\n"},"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"submitted_at":{"type":"string","format":"date-time","description":"Datum podania podnetu obcanom (digiobcan.reports.inserted_at).\nV zozname pre admina je totozny s `inserted_at` - riadok je cele\npodnet, takze aj `inserted_at` je datum jeho podania, nie\ndatum vzniku nalezu (ten je na kazdom prvku `issues`).\n`deadline_at` sa pocita z tohto pola.\n"},"deadline_at":{"type":"string","format":"date-time","description":"Lehota na vyjadrenie - datum podania podnetu\n(submitted_at) + N kalendarnych dni.\nN je konfigurovatelne cez `reports.responseDeadlineDays`.\n"},"overdue":{"type":"boolean","description":"true, ak lehota na vyjadrenie uz uplynula a aspon jeden\nz pristupnych nalezov podnetu je stale nepridelen[y]\n(status `open`). Lehota bezi po **prijatie** nalezu, nie po\njeho vyriesenie. Rovnako to plati v zozname aj v detaile.\n"}}}]},{"type":"object","properties":{"location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"description":{"type":"string"},"issuedReportCategories":{"type":"array","description":"List of unique category IDs this report belongs to","items":{"type":"string","description":"Category ID"}}}}]},"ReportStatusItem":{"type":"object","description":"Jeden krok casovej osi podnetu tak, ako ju vidi obcan: nalez, ktory\nurad prijal (`accepted`), uzavrel (`resolved`) alebo zlucil ako duplikat\n(`duplicate`), plus vyjadrenia, ktore k nemu urad zverejnil.\n\nPri `duplicate` su vo `statements` vyjadrenia **originalu**, nie tohto\nnalezu - duplikat preberá riesenie aj vyjadrenie toho, do ktoreho bol\nzluceny, a vlastne stanovisko sa nezverejnuje.\n","required":["status","date","categoryName"],"properties":{"issue_id":{"type":"string","description":"Nalez, ktoreho sa krok tyka"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"date":{"type":"string","format":"date-time","description":"Date of the status change in ISO 8601 format"},"categoryName":{"type":"string","description":"Name of the category associated with the status"},"statements":{"type":"array","description":"Zverejnene vyjadrenia uradu, od najnovsieho.","items":{"type":"object","description":"Vyjadrenie tak, ako ho vidi obcan. Je to `IssueStatement` **bez autora**:\nzverejnuje sa stanovisko uradu, nie meno konkretneho uradnika.\n","required":["statement_id","text","final","media","inserted_at"],"properties":{"statement_id":{"type":"string"},"text":{"type":"string"},"final":{"type":"boolean"},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"}}}}}},"ReportIssuePossibleDuplicate":{"type":"object","required":["id","status","inserted_at","report_id","report_title"],"properties":{"id":{"type":"string","description":"Unique identifier for the issue"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time","description":"Date when the issue was created in ISO 8601 format"},"report_id":{"type":"string","description":"ID of the report associated with the issue"},"report_title":{"type":"string","description":"Title of the report associated with the issue"},"category_id":{"type":"string","description":"Kategoria kandidata. Je vzdy zhodna s kategoriou naleza, ku ktoremu\nsa kandidati hladaju - duplicita je vztah dvoch nalezov v jednej\nkategorii, nie dvoch podnetov ako celkov.\n"},"category_name":{"type":"string"},"embedding_distance":{"type":"number","format":"float","description":"Vzdialenost embeddingov najpodobnejsej dvojice fotiek, tak ako ju\nzapisal detektor (`<->`, teda L2). Mensie je podobnejsie; chyba,\nked ju detektor nezaznamenal. Sluzi na **zoradenie** kandidatov.\n\nPercento zhody sa z nej **nepocita**. Prevod na percenta vyzaduje\nznamu skalu, a tu nemame: embeddingy pochadzaju z embed-servera\na nikde sa nenormalizuju, takze nie je overene, ci plati vztah\n`cos = 1 - d^2/2`. Keby platil, pozorovane vzdialenosti by vsetky\nvysli na 95-99 %, co by kandidatov nerozlisilo a v UI by posobilo\npresnejsie, nez aka informacia za tym je. Skutocna kosinova\npodobnost patri do `reports_possible_duplicates` ako vlastny stlpec,\nktory zapise reports-processor - dovtedy UI ukazuje vzdialenost\nv metroch a poradie.\n"},"distance_meters":{"type":"integer","description":"Vzdialenost medzi polohami oboch podnetov v metroch. Chyba, ked\naspon jedno z nich polohu nema.\n"}}},"ReportCategory":{"type":"object","required":["category_id","name","is_default"],"properties":{"category_id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"},"users_count":{"type":"integer"},"full_path":{"type":"string","description":"Cesta kategorie od korena (`Kancelaria primatora / Komunikacia`).\nSklada ju server, lebo pri filtrovani (`q`) dostane klient utrzok\nstromu, v ktorom rodic byt nemusi.\n"},"users":{"type":"array","description":"Uradnici zodpovedni za kategoriu, zoradeni podla priezviska.\n\nPlni ich **len** `GET /reports-categories`, a aj tam **iba\nvolajucemu s `pruser:report-categories:manage`**. Samotny zoznam\nkategorii staci prihlasenemu uctu (potrebuje ho kazdy uradnik na\nprekategorizovanie nalezu), ale mena uradnikov mesta uz nie su vec,\nktoru ma dostat kazdy prihlaseny. Neopravneny volajuci dostane pole\nprazdne, nie chybu.\n\nExistuje preto, aby administracia vedela vykreslit avatary bez\ndotazu na kazdy riadok. `POST`, `PUT` ani detail kategorie ho\nnevracaju. Meno a priezvisko chyba, kym sa ucet aspon raz\nneprihlasil; `email` sa tu **nevraca nikdy** - na to je\n`GET /reports-categories/{categoryId}/users`.\n","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}}},"is_default":{"type":"boolean","description":"Kategoria, do ktorej padne podnet, ktory sa nepodarilo zaradit.\nPriznak ma najviac jedna kategoria; prehadzuje sa cez\n`PUT /reports-categories/{categoryId}/default`. Stav, ked ho nema\nziadna, je platny - vtedy `reports-processor` nezaradeny podnet\nnema kam odlozit a administracia to hlasi.\n"}}},"ReportStatus":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"NewReportCategory":{"type":"object","description":"`category_id` sa tu **neposiela**. Identifikator generuje server rovnako\nako pri podnetoch, nalezoch a projektoch (`generateIdentifier`), takze\nnezavisi na nazve - kategoriu je mozne premenovat a kluc na to nereaguje.\nKym to tak nebolo, skladal ho klient zo slugu nazvu.\n","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"parent_id":{"type":"string"}}},"UpdateReportCategory":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"parent_id":{"type":"string"}}},"Location":{"type":"object","required":["type","coordinates"],"properties":{"type":{"type":"string","enum":["Point"]},"coordinates":{"type":"array","items":{"type":"number","minItems":2,"maxItems":2,"description":"longitude, latitude in WGS84 format"}}}},"UserDetail":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"},"email":{"type":"string","description":"Kontakt uradnika. Chyba, kym sa ucet aspon raz neprihlasil - riadok\nv `digiobcan.users` zaklada az prve prihlasenie, kdezto priradenie\nku kategorii vznikne uz pri pozvani.\n"}}},"UserCandidate":{"type":"object","description":"Kandidát na priradenie ku kategórii podnetov.\n\nNesie **presne jeden** identifikátor: `client_acc_id`, ak sa človek do\nMôjho Prešova už niekedy prihlásil, inak `acc_id` (identifikátor účtu na\núrovni platformy). Pri priradení sa posiela ten, ktorý prišiel;\n`POST /reports-categories/{categoryId}/users` si z `acc_id` identifikátor\nv aplikácii dorobí.\n","properties":{"client_acc_id":{"type":"string"},"acc_id":{"type":"string"},"name":{"type":"string"},"surname":{"type":"string"}}},"IssueStatementMedia":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}},"IssueStatement":{"type":"object","description":"Vyjadrenie uradu k nalezu tak, ako ho vidi uradnik. Priebezne\n(`final: false`) alebo finalne (`final: true`) - finalne je to, ktorym\nnalez prechadza do stavu `resolved`, a viac nez jedno ich k nalezu byt\nnemoze.\n","required":["statement_id","issue_id","text","final","media","inserted_at"],"properties":{"statement_id":{"type":"string"},"issue_id":{"type":"string"},"text":{"type":"string"},"final":{"type":"boolean"},"author":{"type":"object","nullable":true,"description":"Uradnik, ktory vyjadrenie napisal. `null`, ked jeho ucet uz\nneexistuje - vyjadrenie je audit zaznam a zmazanim uctu nezanika.\nObcanovi sa autor nezobrazuje vobec, viz `PublicIssueStatement`.\n","properties":{"name":{"type":"string"},"surname":{"type":"string"}}},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"PublicIssueStatement":{"type":"object","description":"Vyjadrenie tak, ako ho vidi obcan. Je to `IssueStatement` **bez autora**:\nzverejnuje sa stanovisko uradu, nie meno konkretneho uradnika.\n","required":["statement_id","text","final","media","inserted_at"],"properties":{"statement_id":{"type":"string"},"text":{"type":"string"},"final":{"type":"boolean"},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string","format":"uuid"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"}}},"Issue":{"type":"object","required":["id","report_id","category_id","category_name","status","inserted_at"],"properties":{"id":{"type":"string"},"report_id":{"type":"string"},"category_id":{"type":"string"},"category_name":{"type":"string"},"status":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"parent_id":{"type":"string"},"parent_report_id":{"type":"string"},"resolved_at":{"type":"string","format":"date-time","description":"Kedy nalez presiel do stavu `resolved`. Chyba, ak nie je vyrieseny."},"has_possible_duplicates":{"type":"boolean","description":"Ma nalez aspon jeden navrh na duplicitu? Odvodene z\n`reports_possible_duplicates` - viz `ReportStatus`.\n"},"possible_duplicates_count":{"type":"integer","description":"Pocet navrhov na duplicitu. 0, ked ziadne nie su."},"statements_count":{"type":"integer","description":"Pocet vyjadreni k nalezu vratane finalneho."}}},"unread_count":{"type":"number","description":"Number of unread notifications (max 10)","maximum":10,"minimum":0},"VotingListItem":{"type":"object","required":["voting_id","title","votes_count","verified_accounts_only","inserted_at","forgotten"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"inserted_at":{"type":"string","format":"date-time","description":"Date when the voting was created in ISO 8601 format"},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"already_voted":{"type":"boolean","description":"Odovzdal volajúci účet v tomto hlasovaní hlas? Prítomné len pre prihláseného; neprihlásenému a v administračnom zozname sa nevracia. Anonymný hlas sa k účtu priradiť nedá, takže po ňom zostáva `false` - je to tá istá vlastnosť, kvôli ktorej sa anonymný hlas ani nededuplikuje."},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"allow_anonymous":{"type":"boolean","description":"If true, hlasovať smie aj neprihlásený"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."}}},"VotingDetail":{"type":"object","required":["voting_id","title","votes_count","questions","verified_accounts_only","public","available_results","available_incomplete_results"],"properties":{"voting_id":{"type":"string","description":"Auto-generated unique identifier"},"title":{"type":"string"},"description":{"type":"string","nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","description":"When the voting opens (auto-generated if not provided)"},"open_to":{"type":"string","format":"date-time","description":"When the voting closes"},"votes_count":{"type":"integer","minimum":0,"readOnly":true,"description":"Total number of votes cast (auto-calculated)"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"available_results":{"type":"boolean","description":"Sú výsledky hlasovania prístupné občanovi? Ak `false`, nezverejnia sa ani po uzavretí - zostane len počet hlasov, `getVotingResults` vráti prázdne `questions`. Správca hlasovaní (`pruser:votings:manage`) výsledky vidí bez ohľadu na túto hodnotu."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed. Má význam len pri `available_results: true`; opačná kombinácia je zakázaná CHECK-om v databáze."},"questions":{"type":"array","items":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},"description":"Pri type=scale sú to **tvrdenia**, ktoré hlasujúci hodnotí na škále,\nnie možnosti na výber.\n"}}}},"forgotten":{"type":"boolean","description":"Whether the voting has been forgotten"},"allow_anonymous":{"type":"boolean","description":"Ak true, hlasovať smie aj neprihlásený. Pre anonymného hlasujúceho\nje `already_voted` vždy false - anonymné hlasy sa nededuplikujú.\n"},"already_voted":{"type":"boolean","description":"Whether the user has already voted in this voting"},"my_votes":{"type":"array","description":"Odpovede, ktoré tento účet v hlasovaní odovzdal - to, čo si\nhlasujúci na detaile pozrie po odhlasovaní.\n\nPríde len prihlásenému, ktorý už hlasoval, teda spolu\ns `already_voted: true`. **Anonymný hlas ho nemá** (nie je z čoho\nodvodiť kľúč) a nemá ho ani lístok odovzdaný pred migráciou 000020;\nv oboch prípadoch pole chýba celé. Chýbajúce pole preto znamená\n„nemám čo zobraziť\", nie „nevybral nič\" - prázdne pole sa\nnevracia zámerne.\n\nTvar je zhodný s `SubmitVoteRequest.votes`, aby sa dal priamo vložiť\ndo formulára v režime len na čítanie.\n","items":{"type":"object","required":["question_id","options"],"properties":{"question_id":{"type":"integer"},"options":{"type":"array","items":{"type":"object","required":["option_id"],"properties":{"option_id":{"type":"integer"},"text":{"type":"string","description":"Text otvorenej odpovede, ak ju možnosť má"},"value":{"type":"integer","description":"Hodnotenie tvrdenia pri otázke typu `scale`"}}}}}}}}},"VotingQuestion":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},"description":"Pri type=scale sú to **tvrdenia**, ktoré hlasujúci hodnotí na škále,\nnie možnosti na výber.\n"}}},"VotingQuestionWithResults":{"type":"object","required":["question_id","voting_id","title","type","min_options","max_options","options"],"properties":{"question_id":{"type":"integer","description":"Question identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"title":{"type":"string","description":"Question title"},"description":{"type":"string","nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. `free_text` - jediná možnosť je voľná (textová odpoveď).\n`single_choice` / `multi_choice` - hlasujúci vyberá z možností.\n`scale` - `options` sú tvrdenia a každé sa hodnotí číslom\n`scale_min`..`scale_max`.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"nullable":true,"description":"Dolná hranica škály (len pre type=scale, inak null). `0` znamená, že\nnajnižší bod stupnice je nula - plnohodnotná odpoveď „nepodporujem\",\nnie chýbajúce hodnotenie. `null` pri type=scale čítaj ako `1`; taký\nriadok zapísal kód spred migrácie 000021.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"nullable":true,"description":"Horná hranica škály (len pre type=scale, inak null)"},"scale_min_label":{"type":"string","nullable":true,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","nullable":true,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","items":{"allOf":[{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},{"type":"object","required":["votes_count"],"properties":{"votes_count":{"type":"integer","minimum":0,"default":0,"readOnly":true,"description":"Number of votes for this option (auto-calculated)"},"text_answers":{"type":"array","items":{"type":"string"},"description":"Array of text answers for free type options (only present when type is 'free')"},"average":{"type":"number","format":"float","nullable":true,"readOnly":true,"description":"Priemerné hodnotenie tvrdenia (len pri question.type=scale).\n`null`, keď tvrdenie nikto neohodnotil.\n"},"histogram":{"type":"array","readOnly":true,"description":"Rozdelenie hodnotení tvrdenia (len pri question.type=scale).\nVždy obsahuje všetky hodnoty scale_min..scale_max, aj tie\ns nulovým počtom.\n","items":{"type":"object","required":["value","count"],"properties":{"value":{"type":"integer","minimum":0},"count":{"type":"integer","minimum":0}}}}}}]}}}},"VotingQuestionOption":{"type":"object","required":["option_id","voting_id","question_id","title","type"],"properties":{"option_id":{"type":"integer","description":"Option identifier (number)"},"voting_id":{"type":"string","description":"Associated voting ID"},"question_id":{"type":"integer","description":"Associated question ID"},"title":{"type":"string","description":"Option text/title"},"description":{"type":"string","nullable":true,"description":"Nepovinný popis. Pri tvrdení na škále je to text, ktorý sa\nhlasujúcemu ukáže pod jeho názvom - pri hlasovaní o projektoch\nzámer projektu. Pri možnosti výberu ho dnes nikto nevypĺňa.\n"},"required":{"type":"boolean","nullable":true,"description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok odovzdať? Význam má\n**len pri question.type=scale**; pri ostatných typoch je `null`,\nlebo koľko možností sa smie vybrať, hovoria `min_options`\na `max_options`. `null` pri škále čítaj ako `true`.\n"},"url":{"type":"string","format":"uri","description":"Optional url for the option"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"}}},"CreateVotingRequest":{"type":"object","required":["title","questions","verified_accounts_only","public","available_incomplete_results"],"properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Title of the voting"},"description":{"type":"string","minLength":1,"maxLength":4096,"nullable":true,"description":"Optional description of the voting"},"open_from":{"type":"string","format":"date-time","nullable":true,"description":"When the voting opens (defaults to current time if not provided)"},"open_to":{"type":"string","format":"date-time","nullable":true,"description":"When the voting closes"},"verified_accounts_only":{"type":"boolean","description":"If true, only verified accounts can vote in this voting"},"public":{"type":"boolean","description":"If true, voting is visible to non-authenticated users"},"allow_anonymous":{"type":"boolean","default":false,"description":"Ak true, hlasovať smie aj neprihlásený (vyžaduje sa reCAPTCHA).\nNedá sa kombinovať s `verified_accounts_only`. Anonymné hlasy sa\n**nededuplikujú** - bez účtu nie je z čoho vyrobiť hash účastníka.\n"},"available_results":{"type":"boolean","default":true,"description":"Sprístupniť občanovi výsledky? `false` ich skryje natrvalo - ani po uzavretí sa nezverejnia. Nepovinné a predvolene `true`, aby klient, ktorý o tomto rozhodnutí nevie, vytvoril hlasovanie s doterajším správaním. Pri `false` server zároveň vynúti `available_incomplete_results: false`."},"available_incomplete_results":{"type":"boolean","description":"If true, results (questions) are available before voting is closed"},"questions":{"type":"array","minItems":1,"description":"Questions for the voting","items":{"type":"object","required":["title","min_options","max_options","options"],"properties":{"title":{"type":"string","minLength":1,"maxLength":255,"description":"Question title"},"description":{"type":"string","minLength":1,"maxLength":2048,"nullable":true,"description":"Optional question description"},"min_options":{"type":"integer","minimum":0,"description":"Minimum number of options user must select"},"max_options":{"type":"integer","minimum":1,"description":"Maximum number of options user can select"},"type":{"type":"string","enum":["free_text","single_choice","multi_choice","scale"],"description":"Typ otázky. Zámerne nie je povinný - keď chýba, server ho\ndopočíta z tvaru otázky (tá istá derivácia ako backfill\nv migrácii 000019), takže starý klient ďalej validuje.\nPri `scale` je `options` zoznam tvrdení, `scale_max` je\npovinný, `max_options` server prepíše na počet tvrdení\na `min_options` na počet tých, ktoré sú `required`. Pri\n`free_text` a `single_choice` server prepíše\n`min_options`/`max_options` na 1.\n"},"scale_min":{"type":"integer","minimum":0,"maximum":1,"description":"Dolná hranica škály (len pre type=scale, inak zakázané).\nKeď chýba, je to `1`. `0` dá stupnicu, kde je nula\nplnohodnotná odpoveď („projekt nechcem podporiť\"), nie\nchýbajúce hodnotenie.\n"},"scale_max":{"type":"integer","minimum":2,"maximum":10,"description":"Horná hranica škály. Povinné pre type=scale, inak zakázané."},"scale_min_label":{"type":"string","maxLength":64,"description":"Popis dolného konca škály (nepovinný, len pre type=scale)"},"scale_max_label":{"type":"string","maxLength":64,"description":"Popis horného konca škály (nepovinný, len pre type=scale)"},"options":{"type":"array","minItems":1,"items":{"type":"object","required":["title","type"],"properties":{"title":{"type":"string","maxLength":255,"description":"Option text/title"},"description":{"type":"string","maxLength":2048,"description":"Nepovinný popis tvrdenia - pri hlasovaní o projektoch\nzámer projektu. Zobrazuje sa pod názvom tvrdenia.\n"},"required":{"type":"boolean","description":"Musí byť tvrdenie ohodnotené, aby sa dal lístok\nodovzdať? Keď chýba, je to `true`. Prípustné **len pri type=scale**; pri\nostatných typoch je 400 (`VOTING_REQUIRED_NOT_ALLOWED`),\nlebo počet vybraných možností riadia\n`min_options`/`max_options`. Škála, ktorej sú všetky\ntvrdenia nepovinné, sa smie preskočiť celá - taká\notázka do `votes` vôbec nepríde.\n"},"type":{"type":"string","enum":["choice","free"],"description":"Option type"},"url":{"type":"string","format":"uri","description":"Optional url for the option"}}}}}}}}},"SubmitVoteRequest":{"type":"object","required":["votes"],"properties":{"votes":{"type":"array","minItems":1,"items":{"type":"object","required":["question_id","options"],"properties":{"question_id":{"type":"integer"},"options":{"type":"array","minItems":1,"items":{"type":"object","required":["option_id"],"properties":{"option_id":{"type":"integer"},"text":{"type":"string","maxLength":4096},"value":{"type":"integer","minimum":0,"maximum":10,"description":"Hodnotenie tvrdenia na škále. Povinné pre otázku\ntype=scale, zakázané pre ostatné typy. Škálová odpoveď\ncestuje ako jedna položka `options` na jedno tvrdenie.\n\nDolná hranica je 0, lebo škála smie začínať nulou\n(`scale_min`); že hodnota patrí do rozsahu **tejto**\notázky, kontroluje server.\n"}}}}}}},"recaptchaToken":{"type":"string","description":"reCAPTCHA v3 token. Povinný, keď hlasujúci nie je prihlásený\n(hlasovanie musí mať `allow_anonymous: true`).\n"}}},"ProjectListItem":{"type":"object","required":["project_id","title","inserted_at"],"properties":{"project_id":{"type":"string"},"title":{"type":"string"},"inserted_at":{"type":"string","format":"date-time"}}},"NewProject":{"type":"object","required":["title","description"],"properties":{"title":{"type":"string","minLength":1,"maxLength":256},"description":{"type":"string","maxLength":2048},"media":{"type":"array","items":{"type":"string","format":"binary"}}}},"ProjectDetail":{"type":"object","required":["project_id","title","description","media","inserted_at"],"properties":{"project_id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"media":{"type":"array","items":{"type":"object","required":["media_id","public_url"],"properties":{"media_id":{"type":"string"},"public_url":{"type":"string","format":"uri"},"original_filename":{"type":"string"},"media_type":{"type":"string"}}}},"inserted_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ProjectUpdate":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":256},"description":{"type":"string","maxLength":2048},"media":{"description":"New media to add","type":"array","items":{"type":"string","format":"binary"}}}}},"parameters":{"limit":{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100,"minimum":1}},"offset":{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0,"maximum":1000},"description":"Number of items to skip for pagination"},"location":{"name":"location","description":"Location in WGS84 format (longitude,latitude,radius_in_meters). Radius is optional.","in":"query","schema":{"type":"string","example":"20.123456,49.123456 or 20.123456,49.123456,1000"}},"q":{"name":"q","in":"query","schema":{"type":"string"}},"accountId":{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}},"news_category":{"name":"category","in":"query","required":false,"description":"Category Ids to filter news","schema":{"type":"array","items":{"type":"string"}}},"report_category":{"name":"category","in":"query","required":false,"description":"Category Ids to filter reports","schema":{"type":"array","items":{"type":"string"}}},"report_issue_status":{"name":"status","in":"query","required":false,"description":"Status to filter reports","schema":{"type":"array","items":{"type":"string","description":"Stav nalezu. `open` -> `accepted` -> `resolved` je hlavna cesta,\n`resolved` je terminalny a spat sa otvorit neda. `moved` je nalez\npresunuty do inej kategorie, `duplicate` nalez uzavrety ako duplikat\nineho (`parent_id`), ktory preberá jeho riesenie aj vyjadrenie.\n\nStav `possible_duplicate` tu **uz nie je**. Nebol to stav nalezu, ale\nodvoditelny priznak: nalez ma navrh na duplicitu prave vtedy, ked ma\nriadok v `reports_possible_duplicates`. Nesie ho preto\n`has_possible_duplicates` na `Issue` a `AdminReportListIssue`.\n","enum":["open","moved","accepted","duplicate","resolved"]}}},"report_query":{"name":"q","in":"query","required":false,"description":"Hladany text. Hlada sa v nazve, popise a identifikatore podnetu,\nbez ohladu na velkost pismen a na diakritiku - `vytluk` najde aj\n`Výtluk`.\n","schema":{"type":"string","minLength":1}},"reportId":{"name":"reportId","in":"path","required":true,"description":"Report ID","schema":{"type":"string"}},"issueId":{"name":"issueId","in":"path","required":true,"description":"Report Issue ID","schema":{"type":"string"}},"categoryId":{"name":"categoryId","in":"path","required":true,"description":"Category ID","schema":{"type":"string"}},"lastInsertedAt":{"name":"lastInsertedAt","in":"query","required":false,"description":"Date of the last item to fetch next items after it","schema":{"type":"string","format":"date-time"}},"projectId":{"name":"projectId","in":"path","required":true,"description":"Project ID","schema":{"type":"string"}},"mediaId":{"name":"mediaId","in":"path","required":true,"description":"Media ID","schema":{"type":"string"}},"statementId":{"name":"statementId","in":"path","required":true,"description":"Issue statement ID","schema":{"type":"string"}},"orderDirection":{"name":"orderDirection","in":"query","schema":{"type":"string","enum":["asc","desc"]},"description":"Default is 'desc'"},"adminGetReportsOrderBy":{"name":"orderBy","in":"query","schema":{"type":"string","enum":["votes","date","location"]},"description":"Default is 'date'"},"dateFrom":{"name":"dateFrom","in":"query","required":false,"description":"Filter reports from this date (ISO 8601 format)","schema":{"type":"string","format":"date-time"}},"dateTo":{"name":"dateTo","in":"query","required":false,"description":"Filter reports until this date (ISO 8601 format)","schema":{"type":"string","format":"date-time"}},"overdue":{"name":"overdue","in":"query","required":false,"description":"Filtrovanie podla lehoty na vyjadrenie:\n- true: len podnety po lehote (lehota uplynula a issue je nevyriesena)\n- false: len podnety v lehote alebo uz vyriesene\n- neuvedene: bez filtra\n","schema":{"type":"boolean"}}},"securitySchemes":{"datahubAccount":{"type":"oauth2","description":"DataHub personal account","flows":{"authorizationCode":{"authorizationUrl":"https://auth.presov.sk/authorize","tokenUrl":"https://auth.presov.sk/token","scopes":{"openid":"Get id token"}}}},"optionalDatahubAccount":{"type":"oauth2","description":"DataHub personal account","flows":{"authorizationCode":{"authorizationUrl":"https://auth.presov.sk/authorize","tokenUrl":"https://auth.presov.sk/token","scopes":{"openid":"Get id token"}}}}}}}