Real time API

The real time API is accessed at https://ggs.online-go.com (or https://ggsbeta.online-go.com/ for the beta site) using socket.io.

This API cannot be used in a stand alone fashion and relies heavily on interfacing first and foremost with the REST API, which plays an integral role in providing authentication credentials for real time requests as well as

Reading this interface document

Under each interface section will be a number of "function" blocks. The header of these blocks is the socket.io endpoint you will send messages to in order to perform your desired action. For example to connect to a game, you'd notice there was a game/connect function listed under the game interface, and thus derive that you needed some code that looked something like

var socket = io.connect("https://online-go.com/");
socket.emit("game/connect", {game_id: 123, player_id: 1, chat: true});

or the equivalent thereof in whatever language you are working in.

Authenticated requests

Authenticated requests use an auth token which is provided via the REST API in various cases. Note you only need to obtain an auth token once for a particular set of actions. For example, in order to make moves on a game you'll need to obtain an auth token for the user and game you are submitting on behalf of and to. Once obtained however, this auth token is valid for that combination of user and game for the duration of the game (and beyond).

SubsystemREST API LocationField
Game playinggames/<game_id>auth
Game chattinggames/<game_id>game_chat_auth
Reviewreviews/<review_id>auth
Review chattingreviews/<review_id>review_chat_auth
Notificationsui/confignotification_auth
General chatui/configchat_auth

Game interface (client to server)

game/connect

Connects you to the game

{
  "player_id": user_id,
  "game_id": game_id,
  "chat": true/false
}

Connects you to a game, after calling this you will receive a game/<id>/gamedata event along with all of the other game related events.

game/disconnect

{
  "game_id": game_id
}

Disconnects you from a game, halting further events emanating from this game.

game/wait

{
  "game_id": game_id
}

When creating an open challenge you will be handed a game_id which you can use to call game/wait with. When the game begins you will receive a game/<id>/reset event notifying you that the game has been started (and that you should reload your game state as your opponent information is now known.)

game/move

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
  "move": "ab"
}

Makes a move at the specified coordinates. Coordinates are encoded like SGF's, a-z to specify each coordinate with aa being the top left.

game/resign

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
}

Resigns from the game

game/conditional_moves/set

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
  "move_number": 123,
  "cmoves": [
    null, {
      "aa": ["bb", {}], 
      "ab": ["ed": {
                      "aa": ["bb": {}]
                   }
            ]
    }
   ]
}

Sets conditional moves for the player. The conditional move object is a tree of the basic format, { "move": ["response move", {...}], ... } where move is the move your opponent makes, response move is the move you respond to, and the object that follows is the conditional moves for the subsequent turns.

At the top level you'll notice the enclosing [null, {...}], this exists for parsing simplicity within the official client, but is otherwise useless. The first value of that array will always be null, the second value of the array is where the interesting stuff begins.

game/removed_stones/set

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
  
  // Stone removal options (must not include seki options)
  "removed": true/false,
  "stones": "ababdbabc",
  
  // Seki options (must not include stone removal options)
  "strict_seki_mode": true/false,
}

Sets or clears the given stones (as specified by a concatenated string of coordinates) for removal, depending on whether removed is true or false.

The strict_seki_mode field is for Japanese rules only and defaults to false. If the user wishes to enforce strict Japanese scoring (which prevents territory in seki from being scored and confuses the majority of players) then set this to true.

📘

Dame is also specified by setting stones

To mark a position as dame, include the position in your stones string and set removed to true.

🚧

Set either the stone removal options or the seki option, not both

Specifically, if the stone removal options exist within the message body, the seki option will be ignored.

📘

Stone removal is collaborative

Both players may mark and unmark stones together during this phase. When using this endpoint, simply set the stones which the player has just selected, the server will merge the requests and send you game/<id>/removed_stones as the state changes.

game/removed_stones/accept

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
  "stones": "abadad",
  "strict_seki_mode": true/false
}

Send this to notify the server the client has accepted the removed stones. The stones string must contain a list of all coordinates that the the player believes are marked dead, and strict_seki_mode should be set to true or false appropriately.

Once both players have accepted the same stones with the same seki mode, the game will be concluded.

game/removed_stones/reject

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
}

Cancels the stone removal phase and resumes the game.

game/cancel

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
}

Cancels the game (which is permitted when the game move number is less than the size of the board). Canceling a game is effectively the same as resigning except neither player suffers any rating or ranking loss.

game/annul

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
}

When playing under Japanese rules, when the board is repeating, a player may annul the game which resets the game back to move 0 and it is played all over again.

game/undo/request

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
  "move_number": 123,
}

Requests an undo from your opponent. move_number must be set to the current move, it is used as a check not as a field to request an undo to a specific move.

game/undo/accept

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
  "move_number": 123,
}

Requests an undo from your opponent. move_number must be set to the current move, it is used as a check not as a field to request an undo to a specific move.

game/pause

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
}

Pauses the game

game/resume

{
  "auth": "abc123",
  "game_id": game_id,
  "player_id": player_id,
}

Resumes the game

game/chat

{
  "auth": "abc123", // NOTE: This is your game_chat_auth not game auth
  "game_id": game_id,
  "player_id": player_id,
  "body": "blah blah",
  "type": "discussion" | "malkovich",
  "move_number": 123,
  "username": "your player username",
  "is_player": true/false,
  "ranking": 0-36,
  "ui_class": "blahblah",
}

Sends a message to either the discussion or malkovich chat log associated with a game. Because we don't want to perform user lookups every time a chat message is sent, the client is responsible for sending along the username, ranking, and ui_class information along with every message (the integrity of these fields is validated with the auth message, so no you can't just make things up ;))

For your ui_class, you can either leave this blank or obtain it from the REST API ui/config endpoint.

Game event messages (server to client)

game//gamedata

The payload of this event contains the entire game state for the given game. It is sent right after a connect is received as well as when the game transitions from the stone removal phase to the finished phase.

This object is fairly large so the documentation has it's own section here:

http://ogs.readme.io/docs/the-game-object

game//clock

Clock events happen when players make moves or when the game is paused or unpaused.

The clock object is thoroughly covered in the time control documentation found here:

http://ogs.readme.io/v4.2/docs/time-control

game//phase

"play" | "stone removal" | "finished"

Indicates you should update the .phase property of the game object and act appropriately

game//undo_requested

move_number

Indicates an undo has been requested at the specified move_number. If this value is not equal to the current move number, you should disregard this event.

game//undo_accepted

move_number

Indicates an undo has been accepted. You should now revert one move to be in sync with the server.

game//move

{ 
  "move": "ab" 
}

Indicates a move has been made at the specified coordinates. You should update the game state accordingly to be in sync with the server.

game//conditional_moves

[null, {...}]

Indicates there are conditional moves that the player has previously specified for this game. This event is part of the data stream that comes after a connect to a game. The format and structure of this is identical to the cmove field specified in the game/conditional_moves/set call.

game//removed_stones

{
  "removed": true/false,
  "stones": "aabbcc",
  
  // or 
  "strict_seki_mode": true/false,
}

Indicates the provided moves or the strict_seki_mode has been updated. See game/conditional_moves/set for more information on these fields.

The client should incorporate the removed/unremoved state of the given coordinates appropriately to be in sync with the server.

game//removed_stones_accepted

{
  "player_id": 123,
  "stones": "abacad",
  "strict_seki_mode": true/false,
}

Indicates that the given player has accepted the provided stones and seki mode combination.

game//chat

{
  "type": "discussion" | "malkovich",
  "message": {
    "username": "...",
    "ranking": 123,
    "ui_class": "...",
    "player_id": 123,
    "date": 1234567890, // unix timestamp
    "body": "string" | {
      "type": "analysis",
      "name": "...",
      "from": move_number,
      "moves": "aababc",
      "marks": {
        "1": "ab",
        "2": "ba",
        "3": "bc",
        "A": "dd",
        "circle": "ee"
      }
    }
  }
}

Indicates a chat message has been sent to a game chat log. The body field may either be a string (ie a normal chat message), or an object indicating a more complex message. Currently the only supported complex message is an analysis aka variation share, which can be used to show game variations from a particular move number along with various markings on the board.

🚧

Don't count on ranking or ui_class to exist

Older games records don't always have these fields.

❗️

Older games have a 1-indexed branch_move field instead of a 0-indexed from field

If branch_move exists instead of from, use branch_move - 1 as your "from" value instead.

"some message"

A message that should be displayed to the user

game//error

"Some error message"

Indicates an error has occurred. These are usually errors associated with bad requests and the like, however the one notable exception occurs when trying to access a private game when the player doesn't have access to the game. The message in this case will be exactly the string This is a private game, so you may use this to display an internationalized version of the string an display it to the user if you wish.

game//reset

{
  "message": "Some message",
  "gamestart_beep": true, // optional
}

Indicates the game should be reloaded. If gamestart_beep is true, it indicates that this event was triggered by the start of the game and if appropriate, the client may wish to give some indication to the user that the game has begun. (This is useful for clients where focus may not be held on a game while the player is waiting for the game to start).

The two normal causes for reset messages are when the game begins and when the game ends. The resets are used to trigger full game reloads as some state may have changed, such as the filling out of the player details (as is the case when an open challenge is accepted), or when the chat log is filled in with any spectator chat for the players (when the game is finished). In either event, if these details are uninteresting there is no need to actually perform a reload when you receive this event, it is simply an indicator that you might want to.

Review & demo interface

📘

Demo boards are reviews

For all intents and purposes, demos are the same thing as reviews except they start with a blank board instead of a prepopulated board position. As such, they use the same API in every respect, so can be use interchangeably.

Chat interface

Notification interface

Seek graph interface