{"openapi":"3.0.1","info":{"title":"Port Royal Back End","description":"The Port Royal Game APIs","version":"1.0"},"servers":[{"url":"http://localhost:8080"},{"url":"https://prbe.mightyshaman.com"}],"tags":[{"name":"Sentinel","description":"Notification subscription APIs"},{"name":"Move","description":"APIs for playing the game"},{"name":"Match","description":"Matches operations"},{"name":"Cards","description":"Card operations"},{"name":"User","description":"User operations"}],"paths":{"/api/v1/user/{username}":{"get":{"tags":["User"],"summary":"Retrieve a user","description":"Retrieve a user by username","operationId":"getUser","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"basicAuth":[]}]},"put":{"tags":["User"],"summary":"Update a user","description":"Update user data","operationId":"updateUser","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserReqDto"}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"basicAuth":[]}]},"delete":{"tags":["User"],"summary":"Delete a user","description":"Delete a user by username","operationId":"deleteUser","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/VoidResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match/start":{"put":{"tags":["Match"],"summary":"Start a match","description":"Start a match.\nIf the player is a bot, the _tgId_ header must be set with the username of the player that the bot is playing for.\nThe match must be hosted by the player and not started yet.\nThe match will be started and the players will be able to insert moves.","operationId":"startMatch","parameters":[{"name":"tgId","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match/join":{"put":{"tags":["Match"],"summary":"Join a match","description":"Join a match by keyCode.\nIf the player is a bot, the _tgId_ header must be set with the username of the player that the bot is playing for.\nThe match must be hosted by someone else and not started yet.","operationId":"joinMatch","parameters":[{"name":"keyCode","in":"query","required":true,"schema":{"type":"string"}},{"name":"tgId","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match/close":{"put":{"tags":["Match"],"summary":"Close a match","description":"Close a match.\nIf the player is a bot, the _tgId_ header must be set with the username of the player that the bot is playing for.\nThe match can be hosted by the someone else but must be not started yet.\nThe match will be closed and the match will be ended no matter if the match is hosted by the player or not.","operationId":"closeMatch","parameters":[{"name":"tgId","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidResponse"}}}}},"security":[{"basicAuth":[]}]}},"/public/register":{"post":{"tags":["User"],"summary":"Register a new user","description":"Register a new user","operationId":"registerUser","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserReqDto"}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}}}},"/api/v1/user/unify":{"post":{"tags":["User"],"summary":"Unify Telegram and email accounts","description":"This endpoint is used to unify telegram and email accounts.\nThis endpoint can be used only by the bot.\nIf the user is already registered with both telegram and email, the telegram account and email account can be unified.","operationId":"unifyTelegramAndEmailAccounts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TgAccountUnificationRequest"}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/user/register/telegram":{"post":{"tags":["User"],"summary":"Register a telegram player","description":"This endpoint is used to register a telegram player and can be used only by the bot.","operationId":"registerTelegramPlayer","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserReqDto"}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/user/changePsw":{"post":{"tags":["User"],"summary":"Change password","description":"Change the password of the current user","operationId":"changePassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordReqDto"}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/VoidResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/sentinel/callback/subscribe":{"post":{"tags":["Sentinel"],"summary":"Subscribe to a callback notification","description":"Subscribe to a callback notification.\nThe callback will be sent to the URL specified in the request.\nThe callback will be sent when a new alert is available.\nThe alert will be sent in the request body.\nThe alert will be sent only once.\nThe alerts refer to any match, that's why the matchKeyCode is required.","operationId":"addCallbackSentinel","requestBody":{"description":"Callback request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackSentinelRequest"},"example":{"matchKeyCode":"xxxxxx","url":"http://localhost:8080/callback"}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match/host":{"post":{"tags":["Match"],"summary":"Host a match","description":"Host a match.\nIf the player is a bot, the _tgId_ header must be set with the username of the player that the bot is playing for.\nThe match must not be hosted by the player yet.\nThe match will be hosted with the provided configuration, if any. Otherwise, the default configuration will be used.\nThe match will be hosted with the player as the first player.\nThe new match keyCode will be returned in the response.","operationId":"hostMatch","parameters":[{"name":"tgId","in":"header","description":"Bot mandatory header","required":false,"schema":{"type":"string"}}],"requestBody":{"description":"Match configuration request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchConfigReqDto"},"example":{"id":1,"name":"default"}}}},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchInfoResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/game/move":{"get":{"tags":["Move"],"summary":"Get a move","description":"Get a single move by match keyCode and move number","operationId":"getMove","parameters":[{"name":"keyCode","in":"query","required":true,"schema":{"type":"string"}},{"name":"moveNumber","in":"query","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MoveResponse"}}}}},"security":[{"basicAuth":[]}]},"post":{"tags":["Move"],"summary":"Insert a move","description":"Make a move in the game.\nIf the player is a bot, the _tgId_ header must be set with the username of the player that the bot is playing for.\nThe move is possible only if the game is in the correct state and the player is the current player.","operationId":"move","parameters":[{"name":"tgId","in":"header","description":"Bot mandatory header","required":false,"schema":{"type":"string"}}],"requestBody":{"description":"New Move request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveReqDto"},"example":{"move":"COMMIT_EXPEDITION","parameterIndex":0,"pickPlayerIndex":-1,"expeditionEmployeesList":["CAPTAIN","CAPTAIN","SETTLER"]}}},"required":true},"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/user":{"get":{"tags":["User"],"summary":"Get user by telegram id or email","description":"Get user by telegram id or email.\nJust one of them is required, if both are provided, telegram id will be used","operationId":"getUserByTelegramId","parameters":[{"name":"telegramId","in":"query","required":false,"schema":{"type":"string"}},{"name":"email","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/user/me":{"get":{"tags":["User"],"summary":"Retrieve the current user","description":"Retrieve the current user","operationId":"getCurrentUser","responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/sentinel/sse/subscribe":{"get":{"tags":["Sentinel"],"summary":"Subscribe to a Server-Sent Events notification","description":"Subscribe to a Server-Sent Events notification.\nThe alert will be sent in the response body.\nThe alert will be sent every time a new alert is available.\nThe alerts refer to any match, that's why the matchKeyCode is required.\nThe alert will be sent only if the alert is available before the timeout.","operationId":"addSSESentinel","parameters":[{"name":"keyCode","in":"query","required":true,"schema":{"type":"string"}},{"name":"seconds","in":"query","required":false,"schema":{"minimum":1,"type":"integer","format":"int32","default":3600}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"SSE subscribed","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/AlertDto"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/sentinel/long-polling/subscribe":{"get":{"tags":["Sentinel"],"summary":"Subscribe to a long polling notification","description":"Subscribe to a long polling notification.\nThe alert will be sent in the response body.\nThe alert will be sent only once.\nThe alerts refer to any match, that's why the matchKeyCode is required.\nThe alert will be sent only if the alert is available before the timeout.","operationId":"addLongPollingSentinel","parameters":[{"name":"keyCode","in":"query","required":true,"schema":{"type":"string"}},{"name":"seconds","in":"query","required":false,"schema":{"minimum":10,"type":"integer","format":"int32","default":120}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertDto"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match":{"get":{"tags":["Match"],"summary":"Get matches","description":"Get matches by player username and ended status","operationId":"getMatches","parameters":[{"name":"ended","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"pageNumber","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"sortField","in":"query","required":false,"schema":{"type":"string","default":"CREATED_AT","enum":["CREATED_AT","STARTED_AT","ENDED_AT"]}},{"name":"sortDirection","in":"query","required":false,"schema":{"type":"string","default":"DESC","enum":["ASC","DESC"]}},{"name":"username","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchInfosPageResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match/{keyCode}":{"get":{"tags":["Match"],"summary":"Get a match","description":"Get match by keyCode.\nIf the _moveNumber_ query parameter is not set, the response will contain the match data in the current state.\nIf the _moveNumber_ query parameter is set to the last move number, the response will contain a message\nsaying that there are no new moves. This is useful for polling the match for new moves.","operationId":"getMatch","parameters":[{"name":"keyCode","in":"path","required":true,"schema":{"type":"string"}},{"name":"moveNumber","in":"query","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/match/status":{"get":{"tags":["Match"],"summary":"Get match status","description":"Get the status of the match being played by the player.\nIf the player is a bot, the _tgId_ header must be set with the username of the player that the bot is playing for.\nThe response will contain the match data in the current state.\nIf the player is not playing any match, the response will contain a message saying that no match is currently being played.","operationId":"getMatchStatus","parameters":[{"name":"tgId","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/game/moves":{"get":{"tags":["Move"],"summary":"Get all moves","description":"Get all moves by match keyCode","operationId":"getMoves","parameters":[{"name":"keyCode","in":"query","required":true,"schema":{"type":"string"}},{"name":"pageNumber","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"sortField","in":"query","required":false,"schema":{"type":"string","default":"TIME_INDEX","enum":["TIME_INDEX","ACTIVE_PLAYER","RUNNING_PLAYER","MOVE_NAME","ACTIVE_PLAYER_USERNAME","RUNNING_PLAYER_USERNAME"]}},{"name":"sortDirection","in":"query","required":false,"schema":{"type":"string","default":"ASC","enum":["ASC","DESC"]}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MovesPageResponse"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/card":{"get":{"tags":["Cards"],"summary":"Get all cards","description":"Get all cards from the game","operationId":"getAllCards","responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"List of cards","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CardDto"}}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/card/{id}":{"get":{"tags":["Cards"],"summary":"Get card by id","description":"Get card by id from the game","operationId":"getCardById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"Card found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CardDto"}}}},"404":{"description":"Card not found","content":{"application/json":{}}}},"security":[{"basicAuth":[]}]}},"/api/v1/card/contract":{"get":{"tags":["Cards"],"summary":"Get all contract cards","description":"Get all contract cards from the game","operationId":"getContractCards","responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"List of contract cards","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContractCardDto"}}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/card/contract/{id}":{"get":{"tags":["Cards"],"summary":"Get contract card by id","description":"Get contract card by id from the game","operationId":"getContractCardById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"Contract card found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractCardDto"}}}},"404":{"description":"Contract card not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractCardDto"}}}}},"security":[{"basicAuth":[]}]}},"/api/v1/sentinel/subscription":{"delete":{"tags":["Sentinel"],"summary":"Remove a subscription","description":"Remove a subscription.\nThe subscription will be removed from the user's subscriptions.\nThe subscription will not be available anymore.","operationId":"removeSentinelSubscription","parameters":[{"name":"keyCode","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"400":{"description":"Bad Request","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"408":{"description":"Request Timeout","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidResponse"}}}}},"security":[{"basicAuth":[]}]}}},"components":{"schemas":{"ErrorDetail":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"error":{"type":"string"},"message":{"type":"string"},"errorDetails":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetail"}},"description":{"type":"string"},"suggestion":{"type":"string"}}},"UserReqDto":{"required":["username"],"type":"object","properties":{"username":{"pattern":"^[a-zA-Z0-9\\-_]{5,30}$","type":"string"},"password":{"type":"string"},"firstName":{"maxLength":30,"minLength":0,"pattern":"^[a-zA-Z\\s]*$","type":"string"},"lastName":{"maxLength":30,"minLength":0,"pattern":"^[a-zA-Z\\s]*$","type":"string"},"email":{"type":"string"},"telegramId":{"pattern":"^[0-9]+$","type":"string"}}},"UserDto":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"telegramId":{"type":"string"},"enabled":{"type":"boolean"},"roles":{"type":"array","items":{"type":"string"}}}},"UserResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/UserDto"}}},"CardDto":{"type":"object","properties":{"id":{"type":"integer","description":"The card id","format":"int32","example":101},"type":{"type":"string","description":"The card type","example":"Ship"},"icon":{"type":"string","description":"The card icon","example":"⛵️🔴"},"points":{"type":"integer","description":"The card points if it is card that gives points","format":"int32","example":6},"cost":{"type":"integer","description":"The card cost if it is a card that can be bought","format":"int32","example":3},"color":{"type":"string","description":"The card color if it is a Ship, a Merchant or a Clerk","example":"RED"},"money":{"type":"integer","description":"The card money if it is a Ship or an Expedition","format":"int32","example":2},"power":{"type":"integer","description":"The card power if it is a Ship, a Pirate or a Sailor","format":"int32","example":1},"expeditionEmployees":{"type":"array","description":"The list of employees needed for the expedition","example":["CAPTAIN","CAPTAIN"],"items":{"type":"string","description":"The list of employees needed for the expedition","example":"[\"CAPTAIN\",\"CAPTAIN\"]"}}}},"ContractCardDto":{"type":"object","properties":{"id":{"type":"integer","format":"int32"},"type":{"type":"string","enum":["AUTOMATIC","MANUAL","AUTOMATIC_RENOUNCING","MANUAL_TWO_PROFESSIONS"]},"icon":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"profession1":{"type":"string"},"profession2":{"type":"string"},"park1":{"type":"array","items":{"type":"string"}},"park2":{"type":"array","items":{"type":"string"}},"spots":{"type":"array","items":{"type":"string"}},"rewards":{"type":"array","items":{"type":"integer","format":"int32"}}}},"EventDto":{"type":"object","properties":{"typeCode":{"type":"string"},"typeDesc":{"type":"string"},"playerUsername":{"type":"string"},"involvedCardIds":{"type":"array","items":{"type":"integer","format":"int32"}},"value":{"type":"integer","format":"int32"}}},"MatchDto":{"type":"object","properties":{"players":{"type":"array","items":{"$ref":"#/components/schemas/PlayerDto"}},"table":{"$ref":"#/components/schemas/TableDto"},"activePlayerIndex":{"type":"integer","format":"int32"},"runningPlayerIndex":{"type":"integer","format":"int32"},"currentPhase":{"type":"string"},"setupDone":{"type":"boolean"},"finalTurn":{"type":"boolean"},"matchEnded":{"type":"boolean"},"winnerIndex":{"type":"integer","format":"int32"},"firstActivePlayerIndex":{"type":"integer","format":"int32"},"lastActivePlayerIndex":{"type":"integer","format":"int32"},"repellingShip":{"$ref":"#/components/schemas/CardDto"},"lastMove":{"$ref":"#/components/schemas/MoveDto"},"movesCount":{"type":"integer","format":"int32"},"keyCode":{"type":"string"},"started":{"type":"boolean"},"startedAt":{"type":"string"},"lastMoveAt":{"type":"string"},"createdAt":{"type":"string"},"configurationId":{"type":"integer","format":"int32"},"playerUsers":{"type":"array","items":{"$ref":"#/components/schemas/UserDto"}},"hostUser":{"$ref":"#/components/schemas/UserDto"},"winnerUser":{"$ref":"#/components/schemas/UserDto"},"ended":{"type":"boolean"},"endedAt":{"type":"string"}}},"MatchResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/MatchDto"}}},"MoveDto":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"createdAt":{"type":"string"},"libVersion":{"type":"string"},"configurationId":{"type":"integer","format":"int32"},"matchKeyCode":{"type":"string"},"timeIndex":{"type":"integer","format":"int32"},"activePlayerUsername":{"type":"string"},"activePlayerIndex":{"type":"integer","format":"int32"},"runningPlayerUsername":{"type":"string"},"runningPlayerIndex":{"type":"integer","format":"int32"},"moveName":{"type":"string"},"parameterIndex":{"type":"integer","format":"int32"},"pickPlayerIndex":{"type":"integer","format":"int32"},"expeditionEmployeesList":{"type":"array","items":{"type":"string"}},"notes":{"type":"string"},"mainEvent":{"$ref":"#/components/schemas/EventDto"},"sideEvents":{"type":"array","items":{"$ref":"#/components/schemas/EventDto"}},"currentPhaseName":{"type":"string"}}},"PlayerDto":{"type":"object","properties":{"username":{"type":"string"},"user":{"$ref":"#/components/schemas/UserDto"},"coins":{"type":"integer","format":"int32"},"points":{"type":"integer","format":"int32"},"power":{"type":"integer","format":"int32"},"employees":{"type":"array","items":{"$ref":"#/components/schemas/CardDto"}},"expeditions":{"type":"array","items":{"$ref":"#/components/schemas/CardDto"}},"contractsCompleted":{"type":"integer","format":"int32"},"tradingCapacity":{"type":"integer","format":"int32"},"redShipRenounced":{"type":"integer","format":"int32"},"blackShipRenounced":{"type":"integer","format":"int32"},"shipColorsRepelled":{"type":"array","items":{"type":"string"}},"taxed":{"type":"boolean"},"minorSpeculator":{"type":"integer","format":"int32"},"majorSpeculator":{"type":"boolean"},"wentBust":{"type":"boolean"}}},"TableDto":{"type":"object","properties":{"drawPileSize":{"type":"integer","format":"int32"},"discardPileSize":{"type":"integer","format":"int32"},"harbor":{"type":"array","items":{"$ref":"#/components/schemas/CardDto"}},"expeditions":{"type":"array","items":{"$ref":"#/components/schemas/CardDto"}},"contracts":{"type":"array","items":{"$ref":"#/components/schemas/ContractCardDto"}}}},"VoidResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"type":"object"}}},"TgAccountUnificationRequest":{"required":["email","telegramId","token"],"type":"object","properties":{"email":{"type":"string"},"telegramId":{"type":"string"},"token":{"type":"string"}}},"ChangePasswordReqDto":{"type":"object","properties":{"oldPassword":{"type":"string"},"newPassword":{"type":"string"}}},"CallbackSentinelRequest":{"required":["matchKeyCode","url"],"type":"object","properties":{"matchKeyCode":{"type":"string"},"url":{"type":"string"},"secret":{"type":"string"}}},"MatchConfigReqDto":{"type":"object","properties":{"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"initialCoins":{"type":"integer","format":"int32"},"firstPlayerRandomlyChosen":{"type":"boolean"},"taxedMoney":{"type":"integer","format":"int32"},"taxRate":{"type":"integer","format":"int32"},"bigExpeditionMinimumPlayersNumber":{"type":"integer","format":"int32"},"cargoCoinToPoorestPlayer":{"type":"boolean"},"contractsCardNumber":{"type":"integer","format":"int32"},"maxContractsCompletablePerPlayer":{"type":"integer","format":"int32"},"jomc_ExpansionUsed":{"type":"boolean"}}},"MatchInfoDto":{"type":"object","properties":{"keyCode":{"type":"string"},"started":{"type":"boolean"},"startedAt":{"type":"string"},"lastMoveAt":{"type":"string"},"createdAt":{"type":"string"},"configurationId":{"type":"integer","format":"int32"},"playerUsernames":{"type":"array","items":{"type":"string"}},"hostUsername":{"type":"string"},"winnerUsername":{"type":"string"},"ended":{"type":"boolean"},"endedAt":{"type":"string"},"movesCount":{"type":"integer","format":"int32"}}},"MatchInfoResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/MatchInfoDto"}}},"MoveReqDto":{"title":"Move insert body","required":["move"],"type":"object","properties":{"move":{"type":"string","description":"The move to make","example":"DISCOVER"},"parameterIndex":{"type":"integer","description":"The index of the card on which the move is made","format":"int32","example":0},"pickPlayerIndex":{"type":"integer","description":"The index of the player on which the move is made","format":"int32","example":-1},"expeditionEmployeesList":{"type":"array","description":"The list of employees needed for the expedition (only for COMMIT_EXPEDITION)","example":["CAPTAIN","CAPTAIN","SETTLER"],"items":{"type":"string","description":"The list of employees needed for the expedition (only for COMMIT_EXPEDITION)","example":"[\"CAPTAIN\",\"CAPTAIN\",\"SETTLER\"]"}}},"description":"Request to make a move in the game"},"MoveResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"$ref":"#/components/schemas/MoveDto"}}},"AlertDto":{"type":"object","properties":{"keyCode":{"type":"string"},"code":{"type":"integer","format":"int32"},"description":{"type":"string"},"message":{"type":"string"}}},"MatchInfosPageResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/MatchInfoDto"}},"reqPageNum":{"type":"integer","format":"int32"},"reqPageSize":{"type":"integer","format":"int32"},"actPageSize":{"type":"integer","format":"int32"},"totalPages":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"sortField":{"type":"string"},"sortDirection":{"type":"string"}}},"MovesPageResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/MoveDto"}},"reqPageNum":{"type":"integer","format":"int32"},"reqPageSize":{"type":"integer","format":"int32"},"actPageSize":{"type":"integer","format":"int32"},"totalPages":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"sortField":{"type":"string"},"sortDirection":{"type":"string"}}}},"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic"}}}}