ClanOfTheCloud is a Mobile Gaming Backend as a Service (Baas) Company. You can create an account on our website, and try us with your next social game! We’re scalable, multiplateform and we offer a full API.
The Sandbox servers are:
And the production servers are:
Each of these servers are load balancers… But if one of them goes down, you can failover to another load balancer.
Once you’ve created an account, you can provision a Game in the FrontOffice application in either sandbox or production mode. We’re using a classic APIKEY / APISECRET couple to authenticate all requests.
Every request should have two headers set with your game credentials :
Header | Value |
---|---|
x-apikey | Your API key |
x-apisecret | Your API secret |
After login has been called, HTTP Basic Authentication will be used to authenticate every request.
The 3 authentication headers will look like :
Header | Value |
---|---|
x-apikey | Your API key |
x-apisecret | Your API secret |
Authorization | Basic gamer_id:gamer_secret (base64 encoded) |
Both gamer_id
and gamer_secret
are returned by /v1/gamer/login
.
Note: It is your responsibility to store these to help the user log in later (in RAW mode).
In addition to the App Authentication above, gamers are authenticated too. Before playing, the gamer needs an identity… Login provides such an identity.
The login route is used to authenticate a gamer, and get basic profile information about him.
Note: If an existing gamer can’t be found, a new one is created and returned.
Login for authenticated gamers will use one of these authentication methods :
Facebook Connect: use the ID
and the oauth token
from Facebook
Google+ Sign-in: use the ID
and the oauth token
from Google+
anonymous: use the gamer_id
and the gamer_secret
from a previous login
A JSON object must be sent in the request body with the following structure.
Field | Description | Value |
---|---|---|
network | string, required | can be one of ["anonymous", "facebook", “google”] |
id | string, required | the user ID for this network |
secret | string, required | the user secret/token for this network |
Note: If a new gamer was created, the response code is 201
, 200
otherwise.
The response is a JSON object.
Field | Description | Value |
---|---|---|
gamer_id | string | user_id used in basic authentication for gamer authenticated requests |
gamer_secret | string | secret used in basic authentication for gamer authenticated requests |
profile | json | gamer’s profile, including "name", "email", "nickname", … |
vfs | json | list of key/value associated to the app/game |
gamervfs | json | list of key/value associated to the gamer |
matches | json | array of match currently in open state of the gamer |
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
{
"network": "facebook",
"id" : "1000001010",
"secret" : "CAAIoRjU6xxYBAAy5Ymu...7XAehrcVQBUOG7oBVNatEUZD"
}
200
ShowHideContent-Type: application/json; charset=utf-8
{
"gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
"gamer_secret" : "dsfg5dgfs654ezrt321ds31gdfs654ert",
"profile" : {},
"vfs" : {},
"gamervfs" : {}
}
Content-Type: application/json
x-apikey: INVALID KEY
x-apisecret: INVALID SECRET
{
"network": "facebook",
"id" : "1000001010",
"secret" : "CAAIoRjU6xxYBAAy5Ymu...7XAehrcVQBUOG7oBVNatEUZD"
}
401
ShowHideContent-Type: application/json; charset=utf-8
{
"code" : "Unauthorized",
"message" : "Invalid App Credentials"
}
The login/anonymous route is used to create a new gamer without any informations.
Note: same response as for login route.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
200
ShowHideContent-Type: application/json; charset=utf-8
{
"gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
"gamer_secret" : "dsfg5dgfs654ezrt321ds31gdfs654ert",
"profile" : {},
"vfs" : {},
"gamervfs" : {}
}
Content-Type: application/json
x-apikey: INVALID KEY
x-apisecret: INVALID SECRET
401
ShowHideContent-Type: application/json; charset=utf-8
{
"code" : "Unauthorized",
"message" : "Invalid App Credentials"
}
Log a gamer out
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json; charset=utf-8
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic INVALID GAMER IDENTITY
401
ShowHideContent-Type: application/json; charset=utf-8
{
"code" : "Unauthorized",
"message" : "Invalid Gamer Credentials"
}
Content-Type: application/json
x-apikey: INVALID API KEY
x-apisecret: INVALID API SECRET
Authorization: Basic gamer_id:gamer_secret
401
ShowHideContent-Type: application/json; charset=utf-8
{
"code" : "Unauthorized",
"message" : "Invalid App Credentials"
}
Used to unlink a user account from Facebook or Google+ credentials.
Profile are data related to the user (globally)
Fields can be added one be one, data are merged. The following fields can be set : ["displayName", "lang", "firstName", "lastName", "addr1", "addr2", "addr3", “avatar”]
note : avatar must be an URL, lang is the ISO-639-1 country code (http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
i.e when executing POST /v1/gamer/profile {"displayName": "Wonder Mike"} if the current profile is “profile” : { “email” : “michael@cotc.com” } then the result will be “profile” : { "displayName": "Wonder Mike", “email” : “michael@cotc.com” }
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"displayName": "Wonder Mike"
}
200
ShowHideContent-Type: application/json; charset=utf-8
{
"profile" : {
"displayName": "Wonder Mike",
"email" : "michael@cotc.com"
},
"updated" : true
}
string
(required) the value to match with
number
(optional) Default: 10 number of desired responses
number
(optional) Default: 0 skip the skip
firsts responses
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"count" : 10,
"result" : [
{
"gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
"profile" : {}
}
]
}
string
(required) the id to check
string
(required) the network on which to search "facebook", “google”
string
(required) the id in the network referential to check
Gamer VFS is a key-value store you can use to associate data with a user.
Use it to store state, preferences… any data your user would like to share among devices.
Because you might want to share Gamer VFS data between games you (or other companies) wrote, you can define so called “domains” which protect your data and let use share it securely.
A Domain is a namespace, but you must know the Domain-Key for this domain to have access to it. So to share data stored in a domain, you just have to share the Domain-Key.
Your game has its own private Domain (see in FrontOffice dashboard) which you probably don’t want to share but you can create other domains to share data between apps, or even between app-developers.
Key not found
… the specified key doesn’t exist
Domain not found
… the specified domain doesn’t exist
string
(required) Example: privatethe domain where to retreive the key/value
string
(optional) the desired key, if omited all keys and values of the domains will be returned
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"key" : "data which could be a json"
}
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"key1" : "any json value, object, array for key1",
"key2" : "any json value, object, array for key2",
"key3" : "any json value, object, array for key3",
"key4" : "any json value, object, array for key4"
}
401
ShowHideContent-Type: application/json
{
"code" : "Unauthorized",
"message" : "the gamer token is no longer available, call login again!",
"data" : "optional error data"
}
404
ShowHideContent-Type: application/json
{
"code" : "Key not found",
"message" : "the specified key is not found"
"data" : "optional error data"
}
You can store data easily. Simply send the data to be stored, as a JSON object, in the body of the request. Note that simple strings are not allowed. Arrays and objects are.
if the key doesn’t exist, it’s dynamically created
You can opt to store your data in Amazon S3 storage. It’s the recommended option for values weighting more than 100ko.
With the binary
option, the API will reply with two URLs: one to upload the file to, and the other with the URL to access the value on the internet.
So uploading a binary value becomes a two steps process:
first call PUT
to pre-authorize storage,
then upload the contents directly to Amazon S3’s preauthorized URL.
calling GET
will then return the URL of the value on Amazon S3.
string
(required) Example: privatethe domain where to store the key/value
string
(required) the desired key
string
(optional) use S3 storage
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{"whatever": "your JSON value"}
200
ShowHideContent-Type: application/json
{"done": 1}
401
ShowHideContent-Type: application/json
{
"code" : "Unauthorized",
"message" : "the gamer token is no longer available, call signin!",
"data" : "optional error data"
}
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"done": 1,
"getURL": url,
"putURL": url
}
NOTE : we can't yet distinguish a missing key from an incorrect domain...
Key not found
… the specified key doesn’t exist
Domain not found
… the specified domain doesn’t exist
string
(required) Example: privatethe domain from where to get the key/value
string
(optional) the key to be removed (all if not specified)
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
1
401
ShowHideContent-Type: application/json
{
"code" : "Unauthorized",
"message" : "the gamer token is no longer available, call signin!",
"data" : "optional error data"
}
404
ShowHideContent-Type: application/json
{
"code" : "Key not found",
"message" : "the specified key is not found"
"data" : "optional error data"
}
Game VFS is a key-value store you can use to associate data with a game.
Use it to store level, booard… any data your game would like to share among users.
Key not found
… the specified key doesn’t exist
Domain not found
… the specified domain doesn’t exist
string
(required) Example: privatethe domain where to retreive the key/value
string
(optional) the desired key, if omited all keys and values of the domains will be returned
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
200
ShowHideContent-Type: application/json
{
"key" : "data which could be a json"
}
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
200
ShowHideContent-Type: application/json
{
"key1" : "any json value, object, array for key1",
"key2" : "any json value, object, array for key2",
"key3" : "any json value, object, array for key3",
"key4" : "any json value, object, array for key4"
}
404
ShowHideContent-Type: application/json
{
"code" : "Key not found",
"message" : "the specified key is not found"
"data" : "optional error data"
}
Transactions are used to keep track of any inventory or portfolio or wallet… It’s basic functionality can be used in various contexts.
In the case of an inventory, transactions will add or remove units from it. When used as a portfolio (for virtual currency), transactions add or remove units too. And feel free to invent new uses!
Transactions/portfolios/inventories can be shared between games with domains. The private domain is private to the game but you can create other domains shared between games.
This feature can be used to share a virtual currency between all your games, or to team up with other game developers to implement cross-marketing or any incentive…
A transaction is a Hash where the key is the unit, and the value is a positive (credit) or negative (debit) amount. So a single transaction can both credit and debit different units.
string
(required) Example: privateThe domain used in the transaction
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
transaction: {
"Gold": 100,
"Silver": -2.5,
"Arrows": 20
},
description: "This is an example transaction"
}
200
ShowHide{
"balance": {
"Gold": 130,
"Silver": 0,
"Arrows": 20
},
"achievements": {
"achievementName": {
"type": "limit",
"config": {
"maxValue": 1000,
"unit": "score"
},
"gameData": {
"hidden": true
},
"progress": 1
}
}
}
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"transaction": { "Gold": -1000000},
"description": "Excessive transaction"
}
549
Use this API to list the transactions of the current gamer. You can specify an optional
?unit=xxx
parameter where xxx
is the unit (Silver, Gold or Arrows in our example). If
unit
is specified, the result will only contain transactions about this unit.
Use ?skip
and ?limit
to page through transactions.
Note: the count
returned is the total number of transactions (useful whith paging)
string
(required) Example: privateThe domain used in the transaction
string
(optional) Example: GoldTo restrict the history to a single Unit
number
(optional) Example: 30The number of rows to skip
number
(optional) Example: 10The number of rows to return
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json; charset=utf-8
{ "history" : [
{ "ts": "2014-08-27T16:44:17.796Z", "tx": { "Gold": 100 }, "desc": "jsclient test" },
{ "ts": "2014-08-27T16:02:22.645Z", "tx": { "Gold": -100, "Silver": 1 }, "desc": "jsclient test" },
{ "ts": "2014-08-27T16:02:22.371Z", "tx": { "Gold": 100 }, "desc": "jsclient test" }
],
"count": 3
}
Use this API to get the current balance. It will return a Hash of each unit and the amount held by the gamer. The balance is also returned each time you create a new transaction
string
(required) Example: privateThe domain used in the transaction
Properties are basic type (number, stringn boolean) json
string
(required) the domain
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"Board": "river",
"Level": 20
"Expert": false
}
200
ShowHideContent-Type: application/json
{
"properties" : {
"Board": "river",
"Level": 20
"Expert": false
},
"updated": true
}
string
(required) the domain
string
(required) the domain
Properties are used to allow match making… They are related to a game.
Properties are basic type (number, string, boolean) or array of basic type
string
(required) the domain
string
(required) name of the property
string
(required) the domain
string
(required) name of the property
string
(required) the domain
string
(required) name of the property
Obtains a code for sponsoring. The code is different for each game
string
(required) Example: privatethe domain handling relations
Set the godfather of the current user and give a reward to the godfather.
string
(required) Example: privatethe domain handling relations
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"godfather": "wSde2dF",
"maturity" : 100,
"reward" : {
transaction : { "gold" : 10},
description : "this is a reward tx",
domain : "private"
}
}
200
ShowHideContent-Type: application/json
{
"done" : 1,
"balance" : {},
"achievements : {}
}
438
ShowHideContent-Type: application/json
{
"code" : "alreadyGodchild"
}
Retreive the godfather of the current user.
string
(required) Example: privatethe domain handling relations
Get every godchildren for the current user.
string
(required) Example: privatethe domain handling relations
This is not necessarily the highest score, but only the highest is stored.
string
(required) the domain used for this leaderboard
string
(required) the board where the gamer score in
string
(optional) Default: hightolow the order to sort the board hightolow
or lowtohigh
string
(optional) Default: false if true, override any previous score
string
(required) the domain used for this leaderboard
string
(required) the board where the gamer score in
string
(optional) Default: hightolow deprecated, defaults to leaderboard’s ordering
string
(optional) Default: highscore one of ["highscore", “friendscore”]
number
(optional) Default: 1 th epage number or a special “me” for centered scores
number
(optional) Default: 10 the max returned rows
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"<leaderboard>" : {
"page" : 2,
"maxpage" : 100,
"rankOfFirst" : 10,
scores : [
{ "gamer_id_1":
{ score : 100, info: "whatever", , timestamp : "", profile: {} }
}
{ "gamer_id_2":
{ score : 90, info: "whatever", , timestamp : "", profile: {} }
}
]
}
}
404
ShowHideContent-Type: application/json
{
"code" : "LeaderboardNotFound",
}
402
ShowHideContent-Type: application/json
{
"code" : "NoScoreYet",
"message" : "Asked for centered scores on a gamer who never scores"
}
string
(required) the domain used for this leaderboard
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"easy" : { score:100, info : "desc" , timestamp : ""}
"meduim" : { score:20, info : "desc", timestamp : "" }
"hard" : { score:10, info : "desc", timestamp : "" }
}
Clan of the Cloud let’s you send and receive messages between gamers.
You can use this feature for inter-application messaging too, and use it to send any kind of json message.
Ordered delivery is guaranteed, and acknowledgement (or auto-acknowledgement) of each message is required.
Use this API to send a message to another user from your game. Messages are sent to a specific user, in a specific domain.
You can use domains to send messages accross games (or use private
for messages sent to your game only).
Messages are always JSON objects (not strings nor binary data).
The response body will contain a copy of the message just sent, with an added id
field.
string
(required) Example: privateThe domain
string
(required) Example: 5402cf700530df4fa7ed3629The recepient for the message
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"key": "value",
"anotherKey" : "another value",
"data" : [{
"any": "data"
}]
}
200
ShowHideContent-Type: application/json
{
"id" : "5cf3baf5-742c-4c3c-ad88-d12d84b01574",
"key": "value",
"anotherKey" : "another value",
"data" : [{
"any": "data"
}]
}
This route uses long polling to deliver messages, one at a time. If more than one message was queued, you will have to call receive
more than once.
Normally, you’d setup a loop to call receive
and deliver messages to your game asynchronously.
Receive
will block for a specified amount of time (with ?timeout=ms
) or 50 seconds (the default), and will be unblocked if a message is received, or if the call times out.
When a message is received, the HTTP status code is 200
. If it returns because of the timeout, the response code is 204
.
To guarantee delivery, acknowledgement is necessary, but you can use automatic acknowledgement (?ack=auto
).
If you want to ack messages, pass ?ack=<messageId>
where messageID
is the ID of the latest received message.
If you don’t specify an ?ack
parameter, the message is received with no ackowledgement (to bootstrap the loop).
Choose if you want auto or acknowlegement as it can get hairy to mix both.
string
(required) Example: privateThe domain
string
(optional) Default: auto Example: 5cf3baf5-742c-4c3c-ad88-d12d84b01574The message ID to acknowledge
integer
(optional) Default: 50000 The long polling timeout, in milliseconds
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"id" : "5cf3baf5-742c-4c3c-ad88-d12d84b01574",
"key": "value",
"anotherKey" : "another value",
"data" : [{
"any": "data"
}]
}
204
Clan of the Cloud provides functionality allowing to save the progress of the player and triggering Achievements, like on most popular platforms. This system is device independent and provides the tools required to notify Clan of the Cloud from progress and querying the status of achievements.
Achievements share functionality with the Transaction system. This is because the key/value storage affected by transactions are used to trigger achievements.
Use this API to list the achievements available for your game, along with, for each of them, the progress of the gamer logged in.
string
(required) Example: privateThe domain, use private
to return the default achievemens created for your game in the Front Office
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"achievements": {
"highScore": {
"type": "limit",
"config": {
"maxValue": 1000,
"unit": "score"
},
"gameData": {
"initiallyHidden": true
},
"gamerData": {
"unhidden": true
},
"progress": 0.06
}
}
}
Use this API to set the custom data associated with a gamer for a given achievement. This data is associated between a gamer and an achievement, so you might for instance store data on how the achievement was performed. The whole achievement, as modified is returned.
string
(required) Example: privateThe domain, use private
to return the default achievemens created for your game in the Front Office
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"unhidden": true
}
200
ShowHideContent-Type: application/json
{
"achievement": {
"type": "limit",
"config": {
"maxValue": 1000,
"unit": "score"
},
"gameData": {
"initiallyHidden": true
},
"gamerData": {
"unhidden": true
},
"progress": 0.06
}
}
Use this API to fetch the custom data associated with a gamer for a given achievement.
string
(required) Example: privateThe domain, use private
to return the default achievemens created for your game in the Front Office
Clan of the Cloud provides a simple way to run matches between a set of gamers using on the network. The match system is designed around a centralized game state stored on Clan of the Cloud servers, with gamers participating to the match making a move, updating the global game state and notifying the other players on an asynchronous basis.
This means that this match system is better suited to turn by turn game, rather than real time game such as an MMORPG, which may require a more sophisticated system handled on your servers.
As with other functionality, matches are scoped by domain, allowing to share data amongst multiple games. For more information, please take a look at the section Key-Value Store.
Creates a new match, automatically attached to your gamer ID. Only the maxPlayers
node is required.
Field | Description | Value |
---|---|---|
_id | string | ID of the match, keep it safe to allow for joining it or fetching it later (read only) |
creator | string | ID of the gamer who created the game (read only) |
customProperties | json | JSON containing the user properties of the match (only one level, with numbers or strings as values) |
domain | string | domain to which the match belongs; used for scoping purposes (read only) |
description | string | description of the game (non localized) |
globalState | json | global state of the match, which may be used to reconstruct the game locally (read only) |
lastEventId | string | ID of the last event, which must be passed by any player who wishes to make a move (read only) |
maxPlayers | number | maximum number of players who can join this game |
events | json | list of pending events, cleared whenever a globalState is posted along with a move by one of the players (read only) |
players | array | list of IDs of players participating to the match (read only) |
seed | 31-bit integer | a random number generated upon match creation, to be used by players |
shoe | array | an array of objects that are shuffled when the match starts. You can put anything you want inside and use it as values for your next game. |
status | string | either “running” (meaning that the match is running), either “finished” (meaning that nobody can join the match anymore) (read only) |
The response of most calls only include basic properties. To get all properties, including the global state and event list, you must either create, join or fetch a single match.
string
(required) the domain on which to place the match (use private by default for a domain that is scoped for your game)
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"description": "Sample match for testing",
"maxPlayers": 3
"customProperties": {
"type": "coop"
},
"globalState": {
"startup": "globalState"
},
"shoe": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "54919c51f8d8690000fe5f6c",
"creator": {
"gamer_id": "54919c510bfa2100001bd548",
"profile": {
"displayName": "Guest",
"lang": "en"
}
},
"customProperties": {
"other": "property",
"type": "coop"
},
"description": "Sample match for testing",
"domain": "private",
"events": [],
"globalState": {},
"lastEventId": "54919c51f8d8690000fe5f6b",
"maxPlayers": 3,
"players": [
{
"gamer_id": "54919c510bfa2100001bd548",
"profile": {
"displayName": "Guest",
"lang": "en"
}
}
],
"seed": 1089745184,
"shoe":[2,3,4,1,10,9,7,6,5,8],
"status": "running"
}
}
Lists the matches available for join, using a query to filter the results.
Matches contain an user defined field named customProperties
, which can be used by developers to store and fetch additional details about a game. In the example of a card-based game, one of these properties could store the minimum bet. This information could also be used to help players to join games best suited to their willing. A filter is specified as an URL-encoded JSON containing attributes and the corresponding expected value. No comparison operators are available for now, now is it possible to customize the implementation : when there are more than one attributes, all conditions specified must be met in order for the match to qualify.
The following will return the matches which have a property named type with value being "coop".
GET /v1/gamer/matches?domain=private&properties={"type": "coop"}
string
(required) the domain on which to look for matches (use private by default for a domain that is scoped for your game)
string
(required) a JSON string specifying the properties that need to be present in order to return a match. The JSON uses the filtering syntax as documented above.
(optional) pass this parameter to only list matches to which you are participating.
(optional) pass this to include finished matches in the result. Not recommended but can be used with the participating
filter to gather info about your past games.
(optional) pass this to filter by matches to which you are currently invited. You are only marked as invited to a match until you join it.
number
(optional) the maximum number of matches to return. Used for pagination. Defaults to 30.
number
(optional) the index of the first item to return. Used for pagination. Zero-based, defaults to 0.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"count": 1,
"matches": [
{
"_id": "548721c15b06a5fec3315a97",
"creator": {
"gamer_id": "548721c15b06a5fec3315a95",
"profile": {
"displayName": "Guest",
"lang": "en"
}
},
"customProperties": {
"other": "property",
"type": "coop"
},
"description": "Sample match for testing",
"domain": "private",
"maxPlayers": 3,
"status": "running"
},
]
}
Fetches a given match. The response looks slightly different from that of a list of matches, but the data reported for the match is the same.
string
(required) the ID of the match as previously returned.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "548724abfe4ce589c6f81d22",
"creator": {
"gamer_id": "548724abfe4ce589c6f81d20",
"profile": {
"displayName": "Guest",
"lang": "en"
}
},
"customProperties": {
"other": "property",
"type": "coop"
},
"description": "Sample match for testing",
"domain": "private",
"events": [],
"globalState": {},
"lastEventId": "548724ab612bff89c680e179",
"maxPlayers": 3,
"players": [
{
"gamer_id": "548724abfe4ce589c6f81d20",
"profile": {
"displayName": "Guest",
"lang": "en"
}
}
],
"status": "running"
}
}
404
ShowHideContent-Type: application/json
{
"name": "InvalidMatch",
"message": "The match does not exist",
"status": 404
}
Deletes a match, erasing it along with its history. You need to be the creator of the match to perform this operation.
string
(required) the ID of the match to delete.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"done": 1
}
431
ShowHideContent-Type: application/json
{
"name": "MatchNotFinished",
"message": "This match needs to be finished in order to perform this operation"
}
Join an existing match.
A field named osn
can be passed as shown in the sample request to send a push notification to the users who are not active at the moment.
Any player who has joined the match will automatically receive events indicating changes made to the match. These events happen when a player joins the match, leaves it or posts a move.
These events must be processed by each player prior to issuing additional commands. To do so, there is a parameter, called lastEventId
that is required on some resources and must be set to the ID of the last event from the match. Among other things, this allows to detect race conditions and guarantee the integrity of the game.
This last event comes in two forms: either as a result of a match operation (in which case you can simply pick the lastEventId
field within the server response) if you were the one initating it, or as the event._id
field of the last received event.
In case a player joins the match, the following event will be received by other players:
{
"type": "match.join",
"event": {
"_id": "548866edba0ec600005e1941",
"match_id": "548866ed74c2e0000098db95",
"playersJoined": [
{
"gamer_id": "548866ed74c2e0000098db94",
"profile": {
"displayName": "Guest",
"lang": "en"
}
}
]
},
"id": "9155987d-6322-46d4-9403-e90ab4ba5fa3"
}
In case a player leaves the match, similarly the following event will be received by others:
{
"type": "match.leave",
"event": {
"_id": "548866eeba0ec600005e1948",
"match_id": "548866ed74c2e0000098db95",
"playersLeft": [
{
"gamer_id": "548866ed74c2e0000098db94",
"profile": {
"displayName": "Guest",
"lang": "en"
}
}
]
},
"id": "5007fd0a-1365-4e87-aba8-5d916731e684"
}
In case the match is marked as finished, the following event will be broadcasted to all players except the one who initiated it.
{
"type": "match.finish",
"event": {
"_id": "54784d07a0fcf2000086457d",
"finished": 1,
"match_id": "54784d07f10c190000cb96e3"
},
"id": "d2f908d1-40d8-4f73-802e-fe0086bb6cd5"
}
In case an element was drawn from the shoe, an event like this is fired:
{
"type": "match.shoedraw",
"event": {
"_id": "5492a7c7a6725f0000b59e4f",
"count": 2,
"match_id": "5492a7c6a6725f0000b59e46"
},
"id": "5e4e82c1-d728-4a4b-be40-e4abec320440"
}
Events are broadcasted in other situations, such as moves, but they are described within the related call documentation.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"osn": {"en": "I just joined!", "ja": "tadaima!"}
}
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "5487260cf45e5f84c7cd7225",
"creator": {
"gamer_id": "5487260cf45e5f84c7cd7223",
"profile": {
"displayName": "Guest",
"lang": "en"
}
},
"customProperties": {
"other": "property",
"type": "coop"
},
"description": "Sample match for testing",
"domain": "private",
"events": [
{
"event": {
"_id": "5487260c1d449b84c728d956",
"playersJoined": [
"5487260cf45e5f84c7cd7224"
]
},
"type": "match.join"
}
],
"globalState": {},
"lastEventId": "5487260c1d449b84c728d956",
"maxPlayers": 3,
"players": [
{
"gamer_id": "5487260cf45e5f84c7cd7223",
"profile": {
"displayName": "Guest",
"lang": "en"
}
},
{
"gamer_id": "5487260cf45e5f84c7cd7224",
"profile": {
"displayName": "Guest",
"lang": "en"
}
}
],
"seed": 1089745184,
"shoe":[2,3,4,1,10,9,7,6,5,8],
"status": "running"
}
}
404
ShowHideContent-Type: application/json
{
"name": "InvalidMatch",
"message": "The match does not exist",
"status": 404
}
431
ShowHideContent-Type: application/json
{
"name": "AlreadyJoinedMatch",
"message": "You are already being part of this match"
}
431
ShowHideContent-Type: application/json
{
"name": "MaximumNumberOfPlayersReached",
"message": "This match can not accept any additional player"
}
433
ShowHideContent-Type: application/json
{
"name": "BadMatchID",
"message": "This match does not exist or is not active"
}
Leave a match. This only works if you are currently part of the match, or you will get an HTTP 433.
A field named osn
can be passed as shown in the sample request to send a push notification to the users who are not active at the moment.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"osn": {"en": "Bye bye!", "fi": "Näkemiin!"}
}
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "548726461c4158b4c73d43fa",
"lastEventId": "5487264710de0db4c71fe752",
"status": "finished"
}
}
404
ShowHideContent-Type: application/json
{
"name": "InvalidMatch",
"message": "The match does not exist",
"status": 404
}
433
ShowHideContent-Type: application/json
{
"name": "BadMatchID",
"message": "This match does not exist or is not active"
}
Allows to invite another person to a match. Should be used with private matches. Matches can be made private by using a filter when listing matches. For instance, you may require a property to be present in the match, such as customProperties: {"public": 1}
and filter out by ?properties={"public": 1}
when listing the matches available. In that case, if you want to play against a given set of opponents, you may simply limit the maximum number of players, and invite each of your opponents.
When someone is invited, a message as follows will be received:
{
"type": "match.invite",
"event": {
"_id": "54784d07a0fcf2000086457d",
"match_id": "54784d07f10c190000cb96e3"
"inviter": {
"gamer_id": "5487260cf45e5f84c7cd7223",
"profile": {
"displayName": "Guest",
"lang": "en"
}
}
},
"id": "d2f908d1-40d8-4f73-802e-fe0086bb6cd9"
}
A field named osn
can be passed as shown in the sample request to send a push notification to the users who are not active at the moment.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"osn": {"en": "Please join my super duper game!", "it": "Sei invitato!"}
}
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "5488121cebc67955fb8f42e2",
"lastEventId": "5488121c4d95f055fbadde9a",
"status": "running"
}
}
431
ShowHideContent-Type: application/json
{
"message": "The player is already invited to the match",
"name": "AlreadyInvitedToMatch"
}
433
ShowHideContent-Type: application/json
{
"message": "A passed gamer ID is invalid",
"name": "BadGamerID"
}
433
ShowHideContent-Type: application/json
{
"name": "BadMatchID",
"message": "This match does not exist or is not active"
}
Allows to dismiss an invitation to a match. Works for the authenticated gamer and only if the gamer has been invited previously.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "5488121cebc67955fb8f42e2",
"lastEventId": "5488121c4d95f055fbadde9a",
"status": "running"
}
}
433
ShowHideContent-Type: application/json
{
"name": "BadMatchID",
"message": "This match does not exist or is not active"
}
Posts a move. This will notify a progress in the match. Note that the globalState
is updated incrementally, according to the passed attributes. This means that attributes not passed do not get modified or deleted from the globalState
stored for this game.
This only works if you are currently part of the match, or you will get an HTTP 433.
A field named osn
can be passed as shown in the sample request to send a push notification to the users who are not active at the moment.
Once a match has been started, any player currently belonging to the game is allowed to make moves. It is up to the game itself to determine which players may play and when.
However, one is only allowed to post a move if he is synchronized with the current state of the game. This is done with a parameter named lastEventId
. Every move made by one of the players, this value changes and is returned in the message posted to the other players. The next player must post this value along with his next move, else he will receive an error indicating that he needs to be resynchronized.
A move is made of a move
object (which is basically freeform, and represents a message that will be sent to other players indicating what changed) and an optional game state labelled globalState
. A global game state sould be enough for any player who joins the game to restore the game locally. Thus, when a global state is posted, the list of moves is cleared on the server: only the moves made since the last global state are kept and posted to people who join the game. As such, one can reconstruct the current game by starting from the global state and applying the pending moves.
When a move is posted, all players get notified in the form of an event, looking as follows:
{
"type": "match.move",
"event": {
"_id": "54784176a8df72000049340e",
"player_id": "547841755e4cfe0000bf6907",
"move": {
"what": "changed"
}
},
"id": "d0fb71c1-3cd0-4bbd-a9ec-29cb46cf9203"
}
Important thing: the globalState
node only includes what has changed, not the whole global state of the match.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"move": {
"what": "changed"
},
"globalState": {
"full": "game_state"
},
"osn": {"en": "It is now your turn!", "de": "Spielen Sie jetzt!"}
}
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "548726461c4158b4c73d43fa",
"lastEventId": "5487264710de0db4c71fe752",
"status": "finished"
}
}
400
ShowHideContent-Type: application/json
{
"name": "MissingParameter",
"message": "The parameter is invalid or absent: lastEventId",
"status": 400
}
431
ShowHideContent-Type: application/json
{
"name": "InvalidLastMoveId",
"message": "This move ID is invalid, please resynchronize"
}
Draws an element from the shoe. Works if an array has been posted as shoe when creating the match.
A field named osn
can be passed as shown in the sample request to send a push notification to the users who are not active at the moment.
Along with the seed element that is returned with the detailed version of the match (i.e. when joining or fetching it), the shoe is another element that helps building random generator-based games.
A shoe, as in Casino, is basically a container of possible values that are returned in a random order as they are poked. It could represent the values of the cards for instance. It is possible to have more than once the same element in the shoe (as when having two card sets). The shoe is posted by the person who creates the game and then shuffled. The shoe will remain hidden, with no one having access to it, until the match is finished.
Players can draw one or more elements off the shoe by posting a request to this resource. The shoe is shared with all players, meaning that any element from the shoe is returned only once to a player having requested it.
When all items have been drawn from the shoe and more items are requested, the existing serie is duplicated, shuffled and appended to the current shoe, meaning an endless play can be considered.
Drawing items from the shoe will trigger one event of type match.shoedraw
per request, sent to players except the caller. When the match finishes, fetching detailed info about the match will return the shoe. It can be used by all players to check that the game has been fair: should one player have hacked the game, it is possible to detect it by comparing the shoe to the actual moves.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"osn": {"en": "I just drew something from the shoe!", "fr": "J'ai récupéré un objet du sabot!"}
}
200
ShowHideContent-Type: application/json
{
"drawnItems": [
{
"prop4": "value4"
},
{
"prop3": "value3"
}
],
"match": {
"_id": "5492a7c6a6725f0000b59e46",
"lastEventId": "5492a7c7a6725f0000b59e4f",
"status": "running"
}
}
400
ShowHideContent-Type: application/json
{
"name": "MissingParameter",
"message": "The parameter is invalid or absent: count",
"status": 400
}
431
ShowHideContent-Type: application/json
{
"name": "InvalidLastMoveId",
"message": "This move ID is invalid, please resynchronize"
}
Marks a match as finished, meaning that no other player will be able to join, post moves or even leave the match: consider it frozen and “archived” after this operation. This only works if you are currently part of the match, or you will get an HTTP 433.
A field named osn
can be passed as shown in the sample request to send a push notification to the users who are not active at the moment.
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
{
"osn": {"en": "The match is finished.", "es": "El partido ha terminado."}
}
200
ShowHideContent-Type: application/json
{
"match": {
"_id": "548726461c4158b4c73d43fa",
"lastEventId": "5487264710de0db4c71fe752",
"status": "finished"
}
}
404
ShowHideContent-Type: application/json
{
"name": "InvalidMatch",
"message": "The match does not exist",
"status": 404
}
433
ShowHideContent-Type: application/json
{
"name": "BadMatchID",
"message": "This match does not exist or is not active"
}
If you want to search for something, you probably want to use the indexing API. You can use it to index gamers (for match making), or matches, or anything. It’s free-form, so it can apply to every use case.
It works in parallel to other APIs. For instance, you could create a match, then index it to allow searching matches. Or you could index gamer’s properties for fast retrieval.
So the API is very simple and quite generic.
*Note: * the indexing API is an unauthenticated API: you don’t have to be logged in as a user to use it. You don’t need an
Authorization
HTTP header.
Use this API to add or update an object in an index. You can have as many indexes as you need: one for gamers’ properties, one for matches, one for finished matches… It only depends on what you want to search.
The Request body must have three mandatory attribues: id, properties and payload.
id
is the id of the object you’re indexing. It can be a MatchId, a GamerId, or anyother unique Id.
properties
is an object. It’s attributes will be indexed and searchable. These are the “indexed fields” of the object. These
properties are typed! So if age
is an int, it must always be an int, or an error will be thrown upon insertion.
payload
is also an object. It’s not indexed, but its contents are returned in searches.
string
(required) Example: privateThe domain
string
(required) Example: matchIndexThe index Name
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
{
"_id": '55706319d11b8125d58c8abe',
"properties": {
"rank": "captain",
"age": 28,
"world": "utopia"
},
"payload": {
"name": "Captain America",
"lastPlayed": 1433428652427
}
}
200
ShowHideContent-Type: application/json
{ _index: 'com.clanofthecloud.cloudbuilder.m3nsd85gnqd3',
_type: 'matchIndex',
_id: '55706319d11b8125d58c8abe',
_version: 1,
created: true
}
You can search documents in the index with this API. It allows you to make complex queries.
See the Elastic documentation
to learn the full syntax for the q
parameter. It’s easy and quite powerful.
You can also use the full Elastic search capabilities with full query DSL search. In this case, you’ll send a json document instead of
using the q
and sort
parameters. Please refer to the Elastic full-body search documentation.
string
(required) Example: privateThe domain
string
(required) Example: matchIndexThe index Name
string
(optional) Example: rank:captainThe query string
string
(optional) Example: ["age"]a JSON array of properties names for sorting
int
(optional) Example: 0The first result index
int
(optional) Example: 10The number of results to return
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
200
ShowHideContent-Type: application/json
{ total: 1,
max_score: 1,
hits:
[ { _index: 'com.clanofthecloud.cloudbuilder.m3nsd85gnqd3',
_type: 'matchIndex',
_id: '55706319d11b8125d58c8abe',
_score: 1,
_source: {
"rank": "captain",
"age": 28,
"world": "utopia",
"payload": {
"name": "Captain America",
"lastPlayed": 1433428652427
}
}
}
]
}
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
{
"query": {
"term": {
"rank": "captain"
}
}
}
200
ShowHideContent-Type: application/json
{ total: 1,
max_score: 1,
hits:
[ { _index: 'com.clanofthecloud.cloudbuilder.m3nsd85gnqd3',
_type: 'matchIndex',
_id: '55706319d11b8125d58c8abe',
_score: 1,
_source: {
"rank": "captain",
"age": 28,
"world": "utopia",
"payload": {
"name": "Captain America",
"lastPlayed": 1433428652427
}
}
}
]
}
Use this API if you want to GET a single index entry, by id. Of course, you should use the search API instead if you want to find more than one element.
string
(required) Example: privateThe domain
string
(required) Example: matchIndexThe index Name
string
(required) Example: 55706319d11b8125d58c8abeThe object Id you’re looking for
(required) x-apikey : testgame-key
x-apisecret : testgame-secret
(required) 200
ShowHideContent-Type: application/json
{ _index: 'com.clanofthecloud.cloudbuilder.m3nsd85gnqd3',
_type: 'matchIndex',
_id: '55706319d11b8125d58c8abe',
_version: 1,
found: true,
_source:
{
"rank": "captain",
"age": 28,
"world": "utopia",
"payload": {
"name": "Captain America",
"lastPlayed": 1433428652427
}
}
}
}
When you want to remove an index entry, use this API. If you just want to update an entry, just use POST instead.
string
(required) Example: privateThe domain
string
(required) Example: matchIndexThe index Name
string
(required) Example: 55706319d11b8125d58c8abeThe object Id you’re looking for
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Generated by aglio on 28 Jun 2015
/v2.6/gamer/friends/{domain}/{?status}
string
(required) Example: privatethe domain handling relations
string
(optional)“blacklist” to retrieve the blacklisted gamer’s
Headers
Content-Type: application/json
x-apikey: testgame-key
x-apisecret: testgame-secret
Authorization: Basic gamer_id:gamer_secret
200
ShowHideHeaders
Content-Type: application/json
Body
{ "friends|blacklisted" : [ { "<gamer_id_1>" : { displayName : "gamer1", lang : "en" } }, {"<gamer_id_2>" : { displayName : "gamer2", lang : "fr" } } ] }