openapi: 3.0.0 info: title: Word Assassin API description: API for hosting Word Assassin games on https://assassin.vlad.gg version: 1.0.0 servers: - description: Live url: https://assassin.vlad.gg/api - description: Staging (PR) url: https://staging.assassin.vlad.gg/api - description: Dev url: https://dev.assassin.vlad.gg/api - description: Local url: http://localhost:8787/api paths: /: get: summary: Server infromation description: Provide server information to client operationId: serverInfo tags: - Info responses: 200: description: Server information content: application/json: schema: type: object properties: env: type: string description: Environment for the server enum: - local - dev - staging - live example: local deployment: type: object description: Deployment information properties: version: type: object description: Version information for this deployment. properties: app: $ref: '#/components/schemas/Version' server: $ref: '#/components/schemas/Version' required: - app - server time: type: number description: Timestamp when this deployment was initiated. example: 1689500982905 git: type: object properties: source: type: string description: Source of this deployment, either 'local' or a repository name. example: local ref: type: string description: Branch name of the source for this deployment. example: main sha: type: string description: SHA hash of the source for this deployment. example: 974f66c4142f26909c20a1888bab1fc1e307b678 required: - source - ref - sha required: - version - time urls: type: object description: URLs for the application properties: ui: type: string description: Main frontend UI URL example: http://localhost:8787 admin: type: string description: Admin frontend UI URL example: http://localhost:8787/admin api: type: string description: Backend URL example: http://localhost:8787/api openapi: type: string description: OpenAPI Swagger YAML example: http://localhost:8787/api/openapi/openapi.swagger docs: type: string description: OpenAPI Documentation URL example: http://localhost:8787/api/openapi required: - env - urls /room: get: summary: List rooms description: List all available room names. operationId: listRooms tags: - Room responses: 200: description: List of room names on this server. content: application/json: schema: type: object properties: rooms: type: array items: $ref: '#/components/schemas/BasicRoom' required: - rooms 500: $ref: '#/components/responses/InternalServerError' /room/{room}: get: summary: Get room description: Get information about a room. operationId: getRoom tags: - Room parameters: - $ref: '#/components/parameters/RoomName' responses: 200: description: Room information content: application/json: schema: $ref: '#/components/schemas/Room' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' put: summary: Add room description: Add a new room. operationId: putRoom tags: - Room - Admin security: - JWTAuth: [] requestBody: $ref: '#/components/requestBodies/AddRoomBody' parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 400: $ref: '#/components/responses/RoomExists' 500: $ref: '#/components/responses/InternalServerError' patch: summary: Update room description: Update an existing room's settings. operationId: patchRoom tags: - Room - Admin - GM security: - JWTAuth: [] requestBody: $ref: '#/components/requestBodies/UpdateRoomBody' parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' delete: summary: Delete room description: Delete an existing room. operationId: deleteRoom tags: - Room - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 400: $ref: '#/components/responses/RoomExists' 500: $ref: '#/components/responses/InternalServerError' /room/{room}/reset: post: summary: Reset room description: Resets room's players and status. operationId: resetRoom tags: - Room - Admin - GM security: - JWTAuth: [] - UserAuth: [] parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' /room/{room}/start: post: summary: Start game description: | Starts the game in a room. **Note:** Game will only start if there's 2 or more players in the room. operationId: startRoom tags: - Room - Admin - GM security: - JWTAuth: [] - UserAuth: [] parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 400: description: Not enough players content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: 'Must have at least 2 people signed up!' required: - message 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' /room/{room}/gm: post: summary: Randomly assign GM description: Removes current GM and randomly assigns it to another user. operationId: assignGM tags: - Room - Admin - GM security: - JWTAuth: [] - UserAuth: [] parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' /room/{room}/gm/{name}: post: summary: Set GM description: Removes current GM and assigns it to the user specified. operationId: setGM tags: - Room - Admin - GM security: - JWTAuth: [] - UserAuth: [] parameters: - $ref: '#/components/parameters/RoomName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' /room/{room}/player/{name}: get: summary: Get player description: Get information about a player. operationId: getPlayer tags: - Player - Admin security: - UserAuth: [] - JWTAuth: [] parameters: - $ref: '#/components/parameters/RoomName' - $ref: '#/components/parameters/PlayerName' responses: 200: description: Player information content: application/json: schema: $ref: '#/components/schemas/Player' 400: $ref: '#/components/responses/GameStarted' 404: $ref: '#/components/responses/PlayerNotFound' 500: $ref: '#/components/responses/InternalServerError' put: summary: Add player description: Add a player to the room. operationId: putPlayer tags: - Player - Admin security: - UserAuth: [] - JWTAuth: [] parameters: - $ref: '#/components/parameters/RoomName' - $ref: '#/components/parameters/PlayerName' responses: 200: $ref: '#/components/responses/Success' 400: $ref: '#/components/responses/PlayerExists' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' delete: summary: Delete player description: Delete a player from a room. operationId: deletePlayer tags: - Player - Admin - GM security: - UserAuth: [] - JWTAuth: [] parameters: - $ref: '#/components/parameters/RoomName' - $ref: '#/components/parameters/PlayerName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' /room/{room}/player/{name}/eliminate: post: summary: Eliminate target description: Eliminates player's target, and assigns their target and words to player. operationId: eliminatePlayer tags: - Player security: - UserAuth: [] parameters: - $ref: '#/components/parameters/RoomName' - $ref: '#/components/parameters/PlayerName' requestBody: content: application/json: schema: type: object properties: word: $ref: '#/components/schemas/Word' responses: 200: $ref: '#/components/responses/Success' 400: $ref: '#/components/responses/PlayerEliminated' 404: $ref: '#/components/responses/RoomNotFound' 500: $ref: '#/components/responses/InternalServerError' /wordlist: get: summary: List wordlists description: List all available wordlist names. operationId: listWordList tags: - Wordlist responses: 200: description: List of wordlist names on this server. content: application/json: schema: type: object properties: wordLists: type: array items: $ref: '#/components/schemas/BasicWordlist' required: - wordLists 500: $ref: '#/components/responses/InternalServerError' /wordlist/import: get: summary: Check importable wordlists. description: | Check which wordlists are not imported or need to be updated operationId: checkWordLists tags: - Admin - Wordlist security: - JWTAuth: [] responses: 200: description: Importable word lists content: application/json: schema: type: array items: $ref: '#/components/schemas/ImportableWordList' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' /wordlist/import/{list}: put: summary: Import or update wordlist. description: | Initialize wordlist with default data, or update if needed. operationId: importWordList tags: - Admin - Wordlist security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' /wordlist/{list}: get: summary: Get wordlist description: Get information about a wordlist. operationId: getWordList tags: - Wordlist parameters: - $ref: '#/components/parameters/WordlistName' responses: 200: description: Wordlist information content: application/json: schema: $ref: '#/components/schemas/Wordlist' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' put: summary: Add wordlist description: Add a new empty wordlist. operationId: putWordList tags: - Wordlist - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' requestBody: $ref: '#/components/requestBodies/AddWordlist' responses: 200: $ref: '#/components/responses/Success' 400: $ref: '#/components/responses/WordlistExists' 500: $ref: '#/components/responses/InternalServerError' patch: summary: Update wordlist description: Update wordlist's properties. operationId: patchWordList tags: - Wordlist - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' requestBody: $ref: '#/components/requestBodies/UpdateWordlist' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' delete: summary: Delete wordlist description: Delete a wordlist. operationId: deleteWordList tags: - Wordlist - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' /wordlist/{list}/word/{word}: put: summary: Add word to wordlist description: | Adds an individual word to an existing wordlist. operationId: putWord tags: - Wordlist - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' - $ref: '#/components/parameters/Word' responses: 200: $ref: '#/components/responses/Success' 400: $ref: '#/components/responses/WordExists' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' delete: summary: Delete word from wordlist description: | Deletes an individual word from an existing wordlist. operationId: deleteWord tags: - Wordlist - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' - $ref: '#/components/parameters/Word' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/WordNotFound' 500: $ref: '#/components/responses/InternalServerError' /wordlist/{list}/words: put: summary: Add words to wordlist description: | Adds words to an existing wordlist. If a word already exists in the wordlist, will skip but not error. operationId: putWords tags: - Wordlist - Admin security: - JWTAuth: [] parameters: - $ref: '#/components/parameters/WordlistName' requestBody: $ref: '#/components/requestBodies/WordlistWords' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' delete: summary: Delete words from wordlist description: | Delete words from an existing wordlist. If a word does not exist in the wordlist, will skip but not error. operationId: deleteWords tags: - Wordlist - Admin security: - JWTAuth: [] requestBody: $ref: '#/components/requestBodies/WordlistWords' parameters: - $ref: '#/components/parameters/WordlistName' responses: 200: $ref: '#/components/responses/Success' 404: $ref: '#/components/responses/WordlistNotFound' 500: $ref: '#/components/responses/InternalServerError' /db: get: summary: Get database info description: | Get information about the database and available and applied migrations. operationId: getDatabase tags: - Database - Info responses: 200: description: Database information content: application/json: schema: type: object properties: binding: type: object properties: type: type: string description: Type of database used example: D1 database: type: string description: Name of database used example: assassin-local migrations: type: object properties: current: $ref: '#/components/schemas/Migration' applied: type: array items: $ref: '#/components/schemas/Migration' available: type: array items: $ref: '#/components/schemas/AvailableMigration' required: - current - applied - available 400: $ref: '#/components/responses/NoMigrationsToApply' 500: $ref: '#/components/responses/InternalServerError' /db/migrate: put: summary: Migrate database description: | Migrates database from current version to newest available one. operationId: migrateDatabase tags: - Admin - Database security: - JWTAuth: [] responses: 200: $ref: '#/components/responses/MigrationResult' 400: $ref: '#/components/responses/NoMigrationsToApply' 500: $ref: '#/components/responses/InternalServerError' /db/rollback: put: summary: Rollback migration description: | Rolls back most recently applied migration. operationId: rollbackDatabase tags: - Admin - Database security: - JWTAuth: [] responses: 200: $ref: '#/components/responses/MigrationResult' 400: $ref: '#/components/responses/NoMigrationsToRollback' 500: $ref: '#/components/responses/InternalServerError' /db/reset: put: summary: Reset database description: | Drops all tables in database operationId: resetDatabase tags: - Admin - Database security: - JWTAuth: [] responses: 200: $ref: '#/components/responses/Success' 500: $ref: '#/components/responses/InternalServerError' components: securitySchemes: JWTAuth: type: http scheme: bearer description: Authentication with JWT generated by zhr.one auth UserAuth: type: apiKey in: header name: X-Assassin-User description: Authentication for GM or current user (honour system, please don't abuse) parameters: RoomName: name: room description: Name of room to use. schema: $ref: '#/components/schemas/RoomName' example: galactic in: path required: true PlayerName: name: name description: Name of player within a room. schema: $ref: '#/components/schemas/PlayerName' example: Vlad in: path required: true WordlistName: name: list description: Name of word list to use. schema: $ref: '#/components/schemas/WordlistName' example: card-poison in: path required: true Word: name: word description: Word to add/delete. schema: $ref: '#/components/schemas/Word' example: test in: path required: true requestBodies: AddRoomBody: description: Body for adding rooms. content: application/json: schema: $ref: '#/components/schemas/AddRoomBody' UpdateRoomBody: description: Body for updating rooms. content: application/json: schema: $ref: '#/components/schemas/UpdateRoomBody' AddWordlist: description: Body for adding wordlists. content: application/json: schema: $ref: '#/components/schemas/WordlistBody' UpdateWordlist: description: Body for updating wordlists. content: application/json: schema: $ref: '#/components/schemas/UpdateWordlistBody' WordlistWords: description: Body for adding words to wordlists. content: application/json: schema: $ref: '#/components/schemas/WordsBody' responses: Success: description: Operation executed successfully. content: application/json: schema: type: object properties: message: type: string description: Success message example: ok required: - message InternalServerError: description: Something went wrong processing your request. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Somethng went wrong! required: - message RoomExists: description: Room already exists and cannot be recreated. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Room already exists! RoomNotFound: description: Could not find room. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Room not found! required: - message PlayerEliminated: description: Player has already been eliminated. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Player is not alive! required: - message PlayerExists: description: Player already exists in the room. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Player already exists! required: - message PlayerNotFound: description: Could not find player. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Player not found! required: - message NoWordlist: description: No wordlists specified. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Need to specify wordlists in body! required: - message WordlistExists: description: Wordlist already exists. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Word list already exists! required: - message WordlistNotFound: description: Could not find wordlist. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Word list not found! required: - message WordlistManaged: description: Word list is managed. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Word list is managed! required: - message WordExists: description: Word already exists. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Word already exists! required: - message WordNotFound: description: Could not find word. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Word not found! required: - message GameStarted: description: Game has already started. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: Game has already started! required: - message NoMigrationsToApply: description: No migrations available to apply. content: application/json: schema: type: object properties: message: type: string description: Message for this error. example: No migrations to apply! required: - message NoMigrationsToRollback: description: No migrations available to roll back. content: application/json: schema: type: object properties: message: type: string description: Message for this roll back. example: No migrations to apply! required: - message MigrationResult: description: Migration(s) applied or rolled back successfully. content: application/json: schema: type: object properties: message: type: string description: Message for this operation. example: Migrations applied successfully! oldVersion: $ref: '#/components/schemas/MigrationVersion' newVersion: $ref: '#/components/schemas/MigrationVersion' required: - message - oldVersion - newVersion schemas: BasicPlayer: type: object properties: name: $ref: '#/components/schemas/PlayerName' status: $ref: '#/components/schemas/PlayerStatus' isGM: $ref: '#/components/schemas/PlayerIsGM' required: - name - isGM Player: type: object properties: name: $ref: '#/components/schemas/PlayerName' room: $ref: '#/components/schemas/RoomName' status: $ref: '#/components/schemas/PlayerStatus' target: description: Target the player has to eliminate, if set. type: string example: Ben words: $ref: '#/components/schemas/WordlistArray' isGM: $ref: '#/components/schemas/PlayerIsGM' required: - name - room - status - isGM PlayerStatus: description: The player's status within the room. type: string enum: - alive - eliminated - champion example: alive PlayerIsGM: description: Whether the player is the room's GM (first player added). type: boolean example: true PlayerName: description: Name of a player within a room. type: string example: Vlad BasicRoom: type: object properties: name: $ref: '#/components/schemas/RoomName' status: $ref: '#/components/schemas/RoomStatus' numPlayers: type: number description: Number of players in room usesWords: $ref: '#/components/schemas/RoomUsesWords' numWordLists: type: number description: Number of word lists used in room. required: - name - status - numPlayers - usesWords - numWordLists Room: description: Room information type: object properties: name: $ref: '#/components/schemas/RoomName' usesWords: $ref: '#/components/schemas/RoomUsesWords' numWords: $ref: '#/components/schemas/NumWords' wordLists: $ref: '#/components/schemas/WordlistArray' status: $ref: '#/components/schemas/RoomStatus' players: type: array minItems: 0 items: $ref: '#/components/schemas/BasicPlayer' required: - name - usesWords - status - players AddRoomBody: description: Body when adding or updating a room. type: object properties: usesWords: $ref: '#/components/schemas/RoomUsesWords' UpdateRoomBody: description: Body when adding or updating a room. type: object properties: status: $ref: '#/components/schemas/RoomStatus' usesWords: $ref: '#/components/schemas/RoomUsesWords' wordLists: $ref: '#/components/schemas/WordlistArray' numWords: $ref: '#/components/schemas/NumWords' RoomUsesWords: type: boolean description: Whether the room uses words or standard assassin. example: true default: true RoomName: description: Name of a room. type: string example: galactic RoomStatus: description: The status of the game within a room. type: string enum: - completed - started - ready - not-ready example: not-ready Word: type: string description: A word the player can use to eliminate their target. example: foo NumWords: type: number description: Number of words to provide players on game start, defaults to 3. example: 3 default: 3 ImportableWordList: type: object properties: name: $ref: '#/components/schemas/WordlistName' icon: $ref: '#/components/schemas/WordlistIcon' reason: type: string enum: - 'add' - 'update' example: 'add' required: - name - reason BasicWordlist: type: object properties: name: $ref: '#/components/schemas/WordlistName' icon: $ref: '#/components/schemas/WordlistIcon' numWords: type: number description: Number of words in room managed: $ref: '#/components/schemas/WordlistManaged' required: - name - numWords - managed Wordlist: allOf: - type: object properties: name: $ref: '#/components/schemas/WordlistName' words: $ref: '#/components/schemas/WordlistArray' managed: $ref: '#/components/schemas/WordlistManaged' required: - name - words - managed - $ref: '#/components/schemas/WordlistBody' WordlistArray: type: array description: A list of words that can be used by players to eliminate their opponents. example: ['card-poison', 'card-dagger', 'pokemon'] items: $ref: '#/components/schemas/Word' WordlistDescription: type: string description: Description to use when showing this word list to admins. example: This is a default word list provided by the 'Card Assassins' game. WordlistIcon: type: string description: FontAwesome icon class to use, if set. Do **not** include `fa-` example: plus WordlistManaged: type: boolean description: Whether the wordlist is managed default: false example: true UpdateWordlistBody: type: object properties: description: $ref: '#/components/schemas/WordlistDescription' icon: $ref: '#/components/schemas/WordlistIcon' WordlistBody: type: object properties: description: $ref: '#/components/schemas/WordlistDescription' icon: $ref: '#/components/schemas/WordlistIcon' required: - description WordlistName: type: string description: Name of word list to use. example: card-assassins-poison WordsBody: type: object properties: words: $ref: '#/components/schemas/WordlistArray' required: - words MigrationVersion: type: number description: Database schema version associated with a migration example: 0 MigrationName: type: string description: Name of a migration example: initial-migration AvailableMigration: type: object description: An available database schema migration properties: version: $ref: '#/components/schemas/MigrationVersion' name: $ref: '#/components/schemas/MigrationName' required: - version - name Migration: type: object description: A database schema migration properties: version: $ref: '#/components/schemas/MigrationVersion' name: $ref: '#/components/schemas/MigrationName' applied: type: number description: Timestamp when this migration was applied example: 1689500974682 rolledBack: type: number description: Timestamp when this migration was rolled back example: 1689500982905 required: - version - name - applied Version: type: string description: Version, represented as semver example: '0.1.0'