API Reference
The Codenames Game Server exposes a Connect RPC API. All endpoints use POST with a JSON body.
Services
BotService is implemented by Bots to play Codenames.
A Bot is expected to implement this interface and host their implementation at the port they use when registering. The Gamemaster VM calls these endpoints to coordinate gameplay.
Protocol Overview
This is a stateful protocol where bots must track game state locally.
When the game first starts each participating Bot is informed via the GameStarted method, which contains the initial game information:
- The request tells the Bot what team they are on and what role they have.
- The request contains the IDs of all participating Bots.
- Guessers gets all cards and their words.
- Spymasters gets all cards, their words, and their card types.
On each turn either GiveClue or MakeGuess is called on the appropriate Bot depending on whose turn it is. The request contains a list of moves that has happened in the game since the last time the Bot was called.
The game continues with GiveClue and MakeGuess calls until a team wins. All participating Bots are notified by this via the GameEnded method.
Strike System and Disqualification
Bots are expected to respond correctly and promptly to all requests. If they do not the Gamemaster will track this and potentially disqualify the Bot from the current game.
The following cases are treated as an error by the server:
- Timeouts: not responding within the configured timeout period.
- Connection errors: unable to reach the bot's endpoint.
- Invalid responses: malformed response data.
- Invalid actions: trying to do an illegal game action.
- GameStarted failures: not able to acknowledge a GameStarted call.
If a Bot does any of these it will be counted as a strike for the Bot in the current game. After 3 strikes the Bot will be disqualified and the game will be ended with the opposing team winning.
Strikes are tracked per-bot and per-game. This means that strikes are not shared by a team, and strikes do not affect any other games. Strikes do however persist for the full game and across turns: if a Bot responds badly across three separate turns it is still treated as a disqualification. A bot disqualified in one game can still participate in future games.
After a strike a Bot will be allowed to retry their action. If for instance a Bot tries to reveal a card not on the board range it will count as a strike but will be allowed to retry immediately.
Bots can track their strikes and what error they did in the bot_context field sent in either the GiveClue or MakeGuess requests.
GameStarted
GameStarted is called on each participating Bot when a new game starts.
GiveClue
GiveClue is called for Spymaster Bots on their turns. Bots responds with the clue the want to give to their Guesser Bot.
MakeGuess
MakeGuess is called for Guesser Bots on their turns. Bots respond with the action they want to take: either reveal a card or end the turn.
GameEnded
Called when a game ends to inform the Bot of the final result. Sent to all participating Bots once when the game ends.
GameService for managing the Gamemaster.
This is the primary management API for the Gamemaster, and is hosted by the Gamemaster VM. This service keeps track of:
- Teams that are participating in the Hackathon.
- Bots that are registered to these Teams.
- Games that the Bots play in.
Most of these methods are free for anyone to call. Methods for Bot registration and unregistrations requires a valid Team token though.
CreateGame
Create a new game with the specified bot assignments, returning the Game ID which can be used to track the game.
The game starts immediately upon creation. All Bots that are references in this request must be registered. A Bot cannot be assigned to multiple roles in a single game: i.e. a Bot cannot play with or against itself in the same game.
GetGame
Get the current state of a game by ID.
ListGames
List all games, both ongoing and ended games.
This method is paginated, i.e. only a small list of all games will be returned in a single call. You need to call it repeatedly with new values to continue to list through the full set of games.
ListActiveGames
List all active games. Returns games in descending order by update time, newest game first.
GetGameMoves
Get the move history for a game. Returns moves in chronological order: first move_number first.
This information can be useful if you want to inspect a game after it has finished.
RegisterBot
Register a Bot to participate in games.
Bots must be registered before they can participate in games. The first time you register a Bot for your Team with a given identity_key it will be created and immediately ready for games. If you call this method with an identity_key that has been unregistered the Bot will be reregistered and keep using its history of played games.
You cannot register a Bot that is already registered. You cannot register a Bot on a port that is already in use by another registered Bot.
This method requires a valid Team token, which should be passed in the Authorization header of the request.
ListBots
Lists all registered bots.
UnregisterBot
Unregister a bot by ID.
When you unregister a Bot it will immediately go into an unregistering state. In this state the Bot can still finish playing any ongoing games it is participating in, but it can no longer start any new games. Once all active games are finished the Bot will be set to the unregistered state, and its port will be available for reuse.
This method requires a valid Team token, which should be passed in the Authorization header of the request.
GetBotGames
Getsthe active games for a specific bot.
GetBot
Get detailed information about a specific bot.
Returns the bot's current state, stats, and active games.
GetLeaderboard
Get the current state of the Bot leaderboard.
ListTeams
codenames.v1.GameService/ListTeams( GameServiceListTeamsRequest ) -> GameServiceListTeamsResponseList all teams participating in the Hackathon.
GetTeam
Get detailed information about a specific team.
ListBotsByTeam
List all bots belonging to a specific team.
ListGamesByBot
List all games for a specific bot, both active and completed.
This method is paginated, i.e. only a small list of all games will be returned in a single call. You need to call it repeatedly with new values to continue to list through the full set of games.
Messages
Enums
BotState represents the lifecycle state of a bot.
| Value | Number | Description |
|---|---|---|
BOT_STATE_UNSPECIFIED | 0 | — |
BOT_STATE_REGISTERED | 1 | Bot is registered and can participate in games. This is the normal active state. |
BOT_STATE_UNREGISTERING | 2 | Bot has been scheduled for unregistration and is waiting for active games to complete. The bot cannot join new games but continues in existing ones. The port is still occupied until the bot reaches the UNREGISTERED state. |
BOT_STATE_UNREGISTERED | 3 | Bot has been unregistered. It can no longer participate in games and its port is freed. The bot is still visible in leaderboards and can be re-registered. |
CardType represents the type of card on the board.
Each card has a type that determines what happens when it is revealed by a Guesser.
| Value | Number | Description |
|---|---|---|
CARD_TYPE_UNSPECIFIED | 0 | — |
CARD_TYPE_RED | 1 | Red card. Revealing this helps Red win. |
CARD_TYPE_BLUE | 2 | Blue card. Revealing this helps Blue win. |
CARD_TYPE_NEUTRAL | 3 | Neutral card. Revealing this type of Card immediately ends the Guesser's turn, but does not help either team. |
CARD_TYPE_ASSASSIN | 4 | Assassin card. If revealed immediately ends the game with the guessing team losing. |
GameEndReason indicates why a game ended.
This helps bots understand if the game ended normally or due to disqualification.
| Value | Number | Description |
|---|---|---|
GAME_END_REASON_UNSPECIFIED | 0 | — |
GAME_END_REASON_NORMAL | 1 | Game ended normally: all cards found for a team or the assassin was revealed. |
GAME_END_REASON_RED_DISQUALIFIED | 2 | Red team was disqualified due to bot misbehavior. |
GAME_END_REASON_BLUE_DISQUALIFIED | 3 | Blue team was disqualified due to bot misbehavior. |
GAME_END_REASON_FAILED_GAME_START_NOTIFYING | 4 | Game failed because bots did not respond to the game start notification. |
GAME_END_REASON_ABORTED | 5 | Game was aborted by the server due to some unexpected error. |
GameState represents the current phase of the game.
Games cycle through spymaster and guessing phases until ended.
| Value | Number | Description |
|---|---|---|
GAME_STATE_UNSPECIFIED | 0 | — |
GAME_STATE_SPYMASTER | 1 | Waiting for spymaster to provide a clue. |
GAME_STATE_GUESSING | 2 | Waiting for guesser to make guesses. |
GAME_STATE_ENDED | 3 | Game has ended. |
Role represents which position a bot plays in a game.
| Value | Number | Description |
|---|---|---|
ROLE_UNSPECIFIED | 0 | — |
ROLE_SPYMASTER | 1 | Spymaster role. This Bot gives clues to their Guesser team mate. |
ROLE_GUESSER | 2 | Guesser role. This Bot uses the Spymaster clues and reveals cards. |
Team represents one of the two teams playing the game.
Red goes first and has one extra card (9 vs 8 for Blue).
| Value | Number | Description |
|---|---|---|
TEAM_UNSPECIFIED | 0 | — |
TEAM_RED | 1 | — |
TEAM_BLUE | 2 | — |
Role filter for bot games.
| Value | Number | Description |
|---|---|---|
BOT_ROLE_FILTER_UNSPECIFIED | 0 | All roles (default). |
BOT_ROLE_FILTER_SPYMASTER | 1 | Spymaster role only. |
BOT_ROLE_FILTER_GUESSER | 2 | Guesser role only. |
How to sort the leaderboard.
| Value | Number | Description |
|---|---|---|
LEADERBOARD_SORT_BY_UNSPECIFIED | 0 | — |
LEADERBOARD_SORT_BY_ELO_RATING | 1 | Sort the leaderboard by Bot win rate (despite the naming of the enum). |
LEADERBOARD_SORT_BY_P99_LATENCY | 2 | Sort the leaderboard by Bot P99 reponse latency. |