{"_id":"5467ae1898b68408002689a9","user":"5435c5d2495d5d0800f3a64e","is_link":false,"version":{"_id":"5467ae1798b68408002689a6","project":"5435c6595e1b20200043836f","__v":1,"forked_from":"5435c6595e1b202000438372","createdAt":"2014-11-15T19:48:39.092Z","releaseDate":"2014-11-15T19:48:39.092Z","categories":["5467ae1798b68408002689a7","5467ae1798b68408002689a8"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"4.2.0","version":"4.2"},"project":"5435c6595e1b20200043836f","__v":13,"category":{"_id":"5467ae1798b68408002689a8","pages":["5467ae1898b68408002689a9","5467ae1898b68408002689aa","546b9fb462515a14007ebc7d"],"version":"5467ae1798b68408002689a6","__v":2,"project":"5435c6595e1b20200043836f","sync":{"url":"","isSync":false},"reference":true,"createdAt":"2014-11-15T19:32:50.301Z","from_sync":false,"order":0,"slug":"api","title":"API"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2014-11-15T19:33:06.986Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"basic_auth":false,"results":{"codes":[]},"try":true,"auth":"never","params":[],"url":""},"isReference":false,"order":0,"body":"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`.\n\nThis API cannot be used in a stand alone fashion and relies heavily on interfacing first and foremost with the [REST API](http://docs.ogs.apiary.io/), which plays an integral role in providing authentication credentials for real time requests as well as \n\n# Reading this interface document\nUnder 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\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var socket = io.connect(\\\"https://ggs.online-go.com/\\\");\\nsocket.emit(\\\"game/connect\\\", {game_id: 123, player_id: 1, chat: true});\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nor the equivalent thereof in whatever language you are working in.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Authenticated requests\"\n}\n[/block]\nAuthenticated 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).\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"Game playing\",\n    \"h-0\": \"Subsystem\",\n    \"h-1\": \"REST API Location\",\n    \"h-2\": \"Field\",\n    \"1-0\": \"Game chatting\",\n    \"0-1\": \"games/<game_id>\",\n    \"1-1\": \"games/<game_id>\",\n    \"0-2\": \"auth\",\n    \"1-2\": \"game_chat_auth\",\n    \"2-0\": \"Review\",\n    \"3-0\": \"Review chatting\",\n    \"2-1\": \"reviews/<review_id>\",\n    \"3-1\": \"reviews/<review_id>\",\n    \"2-2\": \"auth\",\n    \"3-2\": \"review_chat_auth\",\n    \"4-0\": \"Notifications\",\n    \"5-0\": \"General chat\",\n    \"4-1\": \"ui/config\",\n    \"5-1\": \"ui/config\",\n    \"4-2\": \"notification_auth\",\n    \"5-2\": \"chat_auth\"\n  },\n  \"cols\": 3,\n  \"rows\": 6\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Game interface (client to server)\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/connect\"\n}\n[/block]\nConnects you to the game\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"player_id\\\": user_id,\\n  \\\"game_id\\\": game_id,\\n  \\\"chat\\\": true/false\\n}\",\n      \"language\": \"json\",\n      \"name\": null\n    }\n  ]\n}\n[/block]\nConnects you to a game, after calling this you will receive a `game/<id>/gamedata` event along with all of the other game related events.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/disconnect\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"game_id\\\": game_id\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nDisconnects you from a game, halting further events emanating from this game.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/wait\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"game_id\\\": game_id\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nWhen 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.)\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/move\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\\"move\\\": \\\"ab\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nMakes a move at the specified coordinates. Coordinates are encoded like SGF's, a-z to specify each coordinate with aa being the top left.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/resign\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nResigns from the game\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/conditional_moves/set\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\\"move_number\\\": 123,\\n  \\\"cmoves\\\": [\\n    null, {\\n      \\\"aa\\\": [\\\"bb\\\", {}], \\n      \\\"ab\\\": [\\\"ed\\\": {\\n                      \\\"aa\\\": [\\\"bb\\\": {}]\\n                   }\\n            ]\\n    }\\n   ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nSets 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.\n\nAt 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/removed_stones/set\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\n  // Stone removal options (must not include seki options)\\n  \\\"removed\\\": true/false,\\n  \\\"stones\\\": \\\"ababdbabc\\\",\\n  \\n  // Seki options (must not include stone removal options)\\n  \\\"strict_seki_mode\\\": true/false,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nSets or clears the given `stones` (as specified by a concatenated string of coordinates) for removal, depending on whether `removed` is true or false.\n\nThe `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.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Dame is also specified by setting `stones`\",\n  \"body\": \"To mark a position as dame, include the position in your `stones` string and set removed to true.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Set either the stone removal options or the seki option, not both\",\n  \"body\": \"Specifically, if the stone removal options exist within the message body, the seki option will be ignored.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Stone removal is collaborative\",\n  \"body\": \"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.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/removed_stones/accept\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\\"stones\\\": \\\"abadad\\\",\\n  \\\"strict_seki_mode\\\": true/false\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nSend 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.\n\nOnce both players have accepted the same stones with the same seki mode, the game will be concluded.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/removed_stones/reject\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nCancels the stone removal phase and resumes the game.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/cancel\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nCancels 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/annul\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nWhen 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/undo/request\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\\"move_number\\\": 123,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nRequests 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/undo/accept\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\\"move_number\\\": 123,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nRequests 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/pause\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nPauses the game\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/resume\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\",\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nResumes the game\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/chat\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"auth\\\": \\\"abc123\\\", // NOTE: This is your game_chat_auth not game auth\\n  \\\"game_id\\\": game_id,\\n  \\\"player_id\\\": player_id,\\n  \\\"body\\\": \\\"blah blah\\\",\\n  \\\"type\\\": \\\"discussion\\\" | \\\"malkovich\\\",\\n  \\\"move_number\\\": 123,\\n  \\\"username\\\": \\\"your player username\\\",\\n  \\\"is_player\\\": true/false,\\n  \\\"ranking\\\": 0-36,\\n  \\\"ui_class\\\": \\\"blahblah\\\",\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nSends 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 ;))\n\nFor your `ui_class`, you can either leave this blank or obtain it from the REST API `ui/config` endpoint.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Game event messages (server to client)\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/gamedata\"\n}\n[/block]\nThe 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. \n\nThis object is fairly large so the documentation has it's own section here: \n\nhttp://ogs.readme.io/docs/the-game-object\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/clock\"\n}\n[/block]\nClock events happen when players make moves or when the game is paused or unpaused.\n\nThe clock object is thoroughly covered in the time control documentation found here:\n\nhttp://ogs.readme.io/v4.2/docs/time-control\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/phase\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"play\\\" | \\\"stone removal\\\" | \\\"finished\\\"\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates you should update the `.phase` property of the game object and act appropriately\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/undo_requested\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"move_number\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/undo_accepted\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"move_number\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates an undo has been accepted. You should now revert one move to be in sync with the server.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/move\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{ \\n  \\\"move\\\": \\\"ab\\\" \\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates a move has been made at the specified coordinates. You should update the game state accordingly to be in sync with the server.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/conditional_moves\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[null, {...}]\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/removed_stones\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"removed\\\": true/false,\\n  \\\"stones\\\": \\\"aabbcc\\\",\\n  \\n  // or \\n  \\\"strict_seki_mode\\\": true/false,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates the provided moves or the strict_seki_mode has been updated. See `game/conditional_moves/set` for more information on these fields. \n\nThe client should incorporate the removed/unremoved state of the given coordinates appropriately to be in sync with the server.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/removed_stones_accepted\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"player_id\\\": 123,\\n  \\\"stones\\\": \\\"abacad\\\",\\n  \\\"strict_seki_mode\\\": true/false,\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates that the given player has accepted the provided stones and seki mode combination.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/chat\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"type\\\": \\\"discussion\\\" | \\\"malkovich\\\",\\n  \\\"message\\\": {\\n    \\\"username\\\": \\\"...\\\",\\n    \\\"ranking\\\": 123,\\n    \\\"ui_class\\\": \\\"...\\\",\\n    \\\"player_id\\\": 123,\\n    \\\"date\\\": 1234567890, // unix timestamp\\n    \\\"body\\\": \\\"string\\\" | {\\n      \\\"type\\\": \\\"analysis\\\",\\n      \\\"name\\\": \\\"...\\\",\\n      \\\"from\\\": move_number,\\n      \\\"moves\\\": \\\"aababc\\\",\\n      \\\"marks\\\": {\\n        \\\"1\\\": \\\"ab\\\",\\n        \\\"2\\\": \\\"ba\\\",\\n        \\\"3\\\": \\\"bc\\\",\\n        \\\"A\\\": \\\"dd\\\",\\n        \\\"circle\\\": \\\"ee\\\"\\n      }\\n    }\\n  }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates 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.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Don't count on ranking or ui_class to exist\",\n  \"body\": \"Older games records don't always have these fields.\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"danger\",\n  \"title\": \"Older games have a 1-indexed branch_move field instead of a 0-indexed from field\",\n  \"body\": \"If `branch_move` exists instead of `from`, use `branch_move - 1` as your \\\"from\\\" value instead.\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"some message\\\"\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nA message that should be displayed to the user\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/error\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\\"Some error message\\\"\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates 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.\n[block:api-header]\n{\n  \"type\": \"fn\",\n  \"title\": \"game/<id>/reset\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"message\\\": \\\"Some message\\\",\\n  \\\"gamestart_beep\\\": true, // optional\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIndicates 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).\n\nThe 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.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Review & demo interface\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"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.\",\n  \"title\": \"Demo boards are reviews\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Chat interface\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Notification interface\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Seek graph interface\"\n}\n[/block]","excerpt":"","slug":"real-time-api","type":"basic","title":"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](http://docs.ogs.apiary.io/), 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 [block:code] { "codes": [ { "code": "var socket = io.connect(\"https://ggs.online-go.com/\");\nsocket.emit(\"game/connect\", {game_id: 123, player_id: 1, chat: true});", "language": "javascript" } ] } [/block] or the equivalent thereof in whatever language you are working in. [block:api-header] { "type": "basic", "title": "Authenticated requests" } [/block] 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). [block:parameters] { "data": { "0-0": "Game playing", "h-0": "Subsystem", "h-1": "REST API Location", "h-2": "Field", "1-0": "Game chatting", "0-1": "games/<game_id>", "1-1": "games/<game_id>", "0-2": "auth", "1-2": "game_chat_auth", "2-0": "Review", "3-0": "Review chatting", "2-1": "reviews/<review_id>", "3-1": "reviews/<review_id>", "2-2": "auth", "3-2": "review_chat_auth", "4-0": "Notifications", "5-0": "General chat", "4-1": "ui/config", "5-1": "ui/config", "4-2": "notification_auth", "5-2": "chat_auth" }, "cols": 3, "rows": 6 } [/block] [block:api-header] { "type": "basic", "title": "Game interface (client to server)" } [/block] [block:api-header] { "type": "fn", "title": "game/connect" } [/block] Connects you to the game [block:code] { "codes": [ { "code": "{\n \"player_id\": user_id,\n \"game_id\": game_id,\n \"chat\": true/false\n}", "language": "json", "name": null } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/disconnect" } [/block] [block:code] { "codes": [ { "code": "{\n \"game_id\": game_id\n}", "language": "json" } ] } [/block] Disconnects you from a game, halting further events emanating from this game. [block:api-header] { "type": "fn", "title": "game/wait" } [/block] [block:code] { "codes": [ { "code": "{\n \"game_id\": game_id\n}", "language": "json" } ] } [/block] 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.) [block:api-header] { "type": "fn", "title": "game/move" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n \"move\": \"ab\"\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/resign" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n}", "language": "json" } ] } [/block] Resigns from the game [block:api-header] { "type": "fn", "title": "game/conditional_moves/set" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n \"move_number\": 123,\n \"cmoves\": [\n null, {\n \"aa\": [\"bb\", {}], \n \"ab\": [\"ed\": {\n \"aa\": [\"bb\": {}]\n }\n ]\n }\n ]\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/removed_stones/set" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n \n // Stone removal options (must not include seki options)\n \"removed\": true/false,\n \"stones\": \"ababdbabc\",\n \n // Seki options (must not include stone removal options)\n \"strict_seki_mode\": true/false,\n}", "language": "json" } ] } [/block] 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. [block:callout] { "type": "info", "title": "Dame is also specified by setting `stones`", "body": "To mark a position as dame, include the position in your `stones` string and set removed to true." } [/block] [block:callout] { "type": "warning", "title": "Set either the stone removal options or the seki option, not both", "body": "Specifically, if the stone removal options exist within the message body, the seki option will be ignored." } [/block] [block:callout] { "type": "info", "title": "Stone removal is collaborative", "body": "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." } [/block] [block:api-header] { "type": "fn", "title": "game/removed_stones/accept" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n \"stones\": \"abadad\",\n \"strict_seki_mode\": true/false\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/removed_stones/reject" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n}", "language": "json" } ] } [/block] Cancels the stone removal phase and resumes the game. [block:api-header] { "type": "fn", "title": "game/cancel" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/annul" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/undo/request" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n \"move_number\": 123,\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/undo/accept" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n \"move_number\": 123,\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/pause" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n}", "language": "json" } ] } [/block] Pauses the game [block:api-header] { "type": "fn", "title": "game/resume" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\",\n \"game_id\": game_id,\n \"player_id\": player_id,\n}", "language": "json" } ] } [/block] Resumes the game [block:api-header] { "type": "fn", "title": "game/chat" } [/block] [block:code] { "codes": [ { "code": "{\n \"auth\": \"abc123\", // NOTE: This is your game_chat_auth not game auth\n \"game_id\": game_id,\n \"player_id\": player_id,\n \"body\": \"blah blah\",\n \"type\": \"discussion\" | \"malkovich\",\n \"move_number\": 123,\n \"username\": \"your player username\",\n \"is_player\": true/false,\n \"ranking\": 0-36,\n \"ui_class\": \"blahblah\",\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "basic", "title": "Game event messages (server to client)" } [/block] [block:api-header] { "type": "fn", "title": "game/<id>/gamedata" } [/block] 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 [block:api-header] { "type": "fn", "title": "game/<id>/clock" } [/block] 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 [block:api-header] { "type": "fn", "title": "game/<id>/phase" } [/block] [block:code] { "codes": [ { "code": "\"play\" | \"stone removal\" | \"finished\"", "language": "json" } ] } [/block] Indicates you should update the `.phase` property of the game object and act appropriately [block:api-header] { "type": "fn", "title": "game/<id>/undo_requested" } [/block] [block:code] { "codes": [ { "code": "move_number", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/<id>/undo_accepted" } [/block] [block:code] { "codes": [ { "code": "move_number", "language": "json" } ] } [/block] Indicates an undo has been accepted. You should now revert one move to be in sync with the server. [block:api-header] { "type": "fn", "title": "game/<id>/move" } [/block] [block:code] { "codes": [ { "code": "{ \n \"move\": \"ab\" \n}", "language": "json" } ] } [/block] Indicates a move has been made at the specified coordinates. You should update the game state accordingly to be in sync with the server. [block:api-header] { "type": "fn", "title": "game/<id>/conditional_moves" } [/block] [block:code] { "codes": [ { "code": "[null, {...}]", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/<id>/removed_stones" } [/block] [block:code] { "codes": [ { "code": "{\n \"removed\": true/false,\n \"stones\": \"aabbcc\",\n \n // or \n \"strict_seki_mode\": true/false,\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/<id>/removed_stones_accepted" } [/block] [block:code] { "codes": [ { "code": "{\n \"player_id\": 123,\n \"stones\": \"abacad\",\n \"strict_seki_mode\": true/false,\n}", "language": "json" } ] } [/block] Indicates that the given player has accepted the provided stones and seki mode combination. [block:api-header] { "type": "fn", "title": "game/<id>/chat" } [/block] [block:code] { "codes": [ { "code": "{\n \"type\": \"discussion\" | \"malkovich\",\n \"message\": {\n \"username\": \"...\",\n \"ranking\": 123,\n \"ui_class\": \"...\",\n \"player_id\": 123,\n \"date\": 1234567890, // unix timestamp\n \"body\": \"string\" | {\n \"type\": \"analysis\",\n \"name\": \"...\",\n \"from\": move_number,\n \"moves\": \"aababc\",\n \"marks\": {\n \"1\": \"ab\",\n \"2\": \"ba\",\n \"3\": \"bc\",\n \"A\": \"dd\",\n \"circle\": \"ee\"\n }\n }\n }\n}", "language": "json" } ] } [/block] 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. [block:callout] { "type": "warning", "title": "Don't count on ranking or ui_class to exist", "body": "Older games records don't always have these fields." } [/block] [block:callout] { "type": "danger", "title": "Older games have a 1-indexed branch_move field instead of a 0-indexed from field", "body": "If `branch_move` exists instead of `from`, use `branch_move - 1` as your \"from\" value instead." } [/block] [block:code] { "codes": [ { "code": "\"some message\"", "language": "json" } ] } [/block] A message that should be displayed to the user [block:api-header] { "type": "fn", "title": "game/<id>/error" } [/block] [block:code] { "codes": [ { "code": "\"Some error message\"", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "fn", "title": "game/<id>/reset" } [/block] [block:code] { "codes": [ { "code": "{\n \"message\": \"Some message\",\n \"gamestart_beep\": true, // optional\n}", "language": "json" } ] } [/block] 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. [block:api-header] { "type": "basic", "title": "Review & demo interface" } [/block] [block:callout] { "type": "info", "body": "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.", "title": "Demo boards are reviews" } [/block] [block:api-header] { "type": "basic", "title": "Chat interface" } [/block] [block:api-header] { "type": "basic", "title": "Notification interface" } [/block] [block:api-header] { "type": "basic", "title": "Seek graph interface" } [/block]