Back to top

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.

Server’s addresses, load balancing and failover

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.

Token-based App Authentication

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 :

HeaderValue
x-apikeyYour API key
x-apisecretYour API secret

After login

After login has been called, HTTP Basic Authentication will be used to authenticate every request.

The 3 authentication headers will look like :

HeaderValue
x-apikeyYour API key
x-apisecretYour API secret
AuthorizationBasic 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).

Login routes 

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

Resources 

/v1/login

Body description

A JSON object must be sent in the request body with the following structure.

FieldDescriptionValue
networkstring, requiredcan be one of ["anonymous", "facebook", “google”]
idstring, requiredthe user ID for this network
secretstring, requiredthe user secret/token for this network

Response description

Note: If a new gamer was created, the response code is 201, 200 otherwise.

The response is a JSON object.

FieldDescriptionValue
gamer_idstringuser_id used in basic authentication for gamer authenticated requests
gamer_secretstringsecret used in basic authentication for gamer authenticated requests
profilejsongamer’s profile, including "name", "email", "nickname", …
vfsjsonlist of key/value associated to the app/game
gamervfsjsonlist of key/value associated to the gamer
matchesjsonarray of match currently in open state of the gamer
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Body
    { 
        "network": "facebook",
        "id" : "1000001010",
        "secret" : "CAAIoRjU6xxYBAAy5Ymu...7XAehrcVQBUOG7oBVNatEUZD"
    }
    
  • Response  200
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {
        "gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
        "gamer_secret" : "dsfg5dgfs654ezrt321ds31gdfs654ert",
        "profile" : {},
        "vfs" : {},
        "gamervfs" : {}
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: INVALID KEY
    x-apisecret: INVALID SECRET
    Body
    { 
        "network": "facebook",
        "id" : "1000001010",
        "secret" : "CAAIoRjU6xxYBAAy5Ymu...7XAehrcVQBUOG7oBVNatEUZD"
    }
    
  • Response  401
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {
        "code" : "Unauthorized",
        "message" : "Invalid App Credentials"
    }
    

Resources 

/v1/login/anonymous

The login/anonymous route is used to create a new gamer without any informations.

Response description

Note: same response as for login route.

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
  • Response  200
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {
        "gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
        "gamer_secret" : "dsfg5dgfs654ezrt321ds31gdfs654ert",
        "profile" : {},
        "vfs" : {},
        "gamervfs" : {}
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: INVALID KEY
    x-apisecret: INVALID SECRET
  • Response  401
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {
        "code" : "Unauthorized",
        "message" : "Invalid App Credentials"
    }
    

Resources 

/v1/gamer/logout

Log a gamer out

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json; charset=utf-8
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic INVALID GAMER IDENTITY
  • Response  401
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {
        "code" : "Unauthorized",
        "message" : "Invalid Gamer Credentials"
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: INVALID API KEY
    x-apisecret: INVALID API SECRET
    Authorization: Basic gamer_id:gamer_secret
  • Response  401
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {
        "code" : "Unauthorized",
        "message" : "Invalid App Credentials"
    }
    

Resources 

/v1/gamer/unlink

Used to unlink a user account from Facebook or Google+ credentials.

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    { 
        "network": "facebook"
    }
    
  • Response  200
  • Headers
    Content-Type: application/json; charset=utf-8

Gamer profile 

Profile 

Profile are data related to the user (globally)

Set Profile
/v1/gamer/profile

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” }

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "displayName": "Wonder Mike"
    }
    
  • Response  200
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    { 
        "profile" : {
            "displayName": "Wonder Mike",
            "email" : "michael@cotc.com"
        },
        "updated" : true
    }
    
Get profile
/v1/gamer/profile
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "properties" : {
            "Board": "river",
            "Level" : 20
            "Expert" : false
        }
    }
    

Gamer Querying 

Find Users 

search
/v1/gamer{?q}{&limit}{&skip}
  • Parameters
  • q
    string (required) 

    the value to match with

    limit
    number (optional) Default: 10 

    number of desired responses

    skip
    number (optional) Default: 0 

    skip the skip firsts responses

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "count" : 10,
        "result" : [
            { 
            "gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
            "profile" : {}
            }
        ]
    }
    

Validate gamer_id 

check
/v1/gamer/gamer_id/{id}
  • Parameters
  • id
    string (required) 

    the id to check

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
        "profile" : {}
    }
    

Find a "Network" gamer_id 

check
/v1/gamer/{network}/{id}
  • Parameters
  • network
    string (required) 

    the network on which to search "facebook", “google”

    id
    string (required) 

    the id in the network referential to check

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "gamer_id" : "dfg54g2dfg54sqdf32wfds54fqdf",
        "profile" : {}
    }
    

Key-Value Store 

Gamer VFS 

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.

Domains

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.

Get gamer's data
/v1/gamer/vfs/{domain}/{key}{?binary}
Possible values for error 404
  • Key not found … the specified key doesn’t exist

  • Domain not found … the specified domain doesn’t exist

  • Parameters
  • domain
    string (required) Example: private

    the domain where to retreive the key/value

    key
    string (optional) 

    the desired key, if omited all keys and values of the domains will be returned

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "key" : "data which could be a json"
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "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"
    }
    
  • Response  401
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "Unauthorized",
        "message" : "the gamer token is no longer available, call login again!", 
        "data" : "optional error data" 
    }        
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "Key not found",
        "message" : "the specified key is not found"
        "data" : "optional error data" 
    }  
    
Set gamer's data
/v1/gamer/vfs/{domain}/{key}{?binary}

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

Optional Binary storage

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.

  • Parameters
  • domain
    string (required) Example: private

    the domain where to store the key/value

    key
    string (required) 

    the desired key

    binary
    string (optional) 

    use S3 storage

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {"whatever": "your JSON value"}
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {"done": 1}
    
  • Response  401
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "Unauthorized",
        "message" : "the gamer token is no longer available, call signin!", 
        "data" : "optional error data" 
    }        
    
  • Request
    • parameters binary : true
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "done": 1,
        "getURL": url,
        "putURL": url
    }
    
Remove gamer's data
/v1/gamer/vfs/{domain}/{key}{?binary}
NOTE : we can't yet distinguish a missing key from an incorrect domain...
Possible reasons for error 404
  • Key not found … the specified key doesn’t exist

  • Domain not found … the specified domain doesn’t exist

  • Parameters
  • domain
    string (required) Example: private

    the domain from where to get the key/value

    key
    string (optional) 

    the key to be removed (all if not specified)

  • Request
  • Headers
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    1
    
  • Response  401
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "Unauthorized",
        "message" : "the gamer token is no longer available, call signin!", 
        "data" : "optional error data" 
    }  
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "Key not found",
        "message" : "the specified key is not found"
        "data" : "optional error data" 
    }  
    

Game VFS 

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.

Get game's data
/v1/vfs/{domain}/{key}
Possible values for error 404
  • Key not found … the specified key doesn’t exist

  • Domain not found … the specified domain doesn’t exist

  • Parameters
  • domain
    string (required) Example: private

    the domain where to retreive the key/value

    key
    string (optional) 

    the desired key, if omited all keys and values of the domains will be returned

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "key" : "data which could be a json"
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "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"
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "Key not found",
        "message" : "the specified key is not found"
        "data" : "optional error data" 
    }  
    

Transactions 

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!

How domains work with transactions

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…

Resources 

/v2.2/gamer/tx/{domain}

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain used in the transaction

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        transaction: { 
            "Gold": 100,
            "Silver": -2.5,
            "Arrows": 20
        },
        description: "This is an example transaction"
    }
    
  • Response  200
  • Body
    {
        "balance": {
            "Gold": 130,
            "Silver": 0,
            "Arrows": 20
        },
        "achievements": {
            "achievementName":     {
                "type": "limit",
                "config": {
                    "maxValue": 1000,
                    "unit": "score"
                },
                "gameData": {
                    "hidden": true
                },
                "progress": 1
            }
        }
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "transaction": { "Gold": -1000000},
        "description": "Excessive transaction"
    }
    
  • Response  549

Resources 

/v2.4/gamer/tx/{domain}{?unit}{&skip}{&limit}

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)

  • Parameters
  • domain
    string (required) Example: private

    The domain used in the transaction

    unit
    string (optional) Example: Gold

    To restrict the history to a single Unit

    skip
    number (optional) Example: 30

    The number of rows to skip

    limit
    number (optional) Example: 10

    The number of rows to return

  • Request
  • Headers
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json; charset=utf-8
    Body
    {   "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
    }
    

Resources 

/v1/gamer/tx/{domain}/balance

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

  • Parameters
  • domain
    string (required) Example: private

    The domain used in the transaction

  • Request
  • Headers
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "Gold": 130,
        "Silver": 1.5,
        "Arrows": 20
    }
    

Gamer Properties 

Properties 

Set properties
/v2.6/gamer/properties/{domain}

Properties are basic type (number, stringn boolean) json

  • Parameters
  • domain
    string (required) 

    the domain

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "Board": "river",
        "Level": 20
        "Expert": false
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "properties" : {
            "Board": "river",
            "Level": 20
            "Expert": false
        },
        "updated": true
    }
    
Get properties
/v2.6/gamer/properties/{domain}
  • Parameters
  • domain
    string (required) 

    the domain

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "properties" : {
            "Board": "river",
            "Level" : 20
            "Expert" : false
        }
    }
    
delete properties
/v2.6/gamer/properties/{domain}
  • Parameters
  • domain
    string (required) 

    the domain

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "done": true
    }
    

Property 

Properties are used to allow match making… They are related to a game.

Set property
/v2.6/gamer/properties/{domain}/{key}

Properties are basic type (number, string, boolean) or array of basic type

  • Parameters
  • domain
    string (required) 

    the domain

    key
    string (required) 

    name of the property

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "value": "river",
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "done" : true
    }
    
Get property
/v2.6/gamer/properties/{domain}/{key}
  • Parameters
  • domain
    string (required) 

    the domain

    key
    string (required) 

    name of the property

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "Board": "river"
    }
    
delete property
/v2.6/gamer/properties/{domain}/{key}
  • Parameters
  • domain
    string (required) 

    the domain

    key
    string (required) 

    name of the property

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "done": true
    }
    

Social features 

Friends

Resources 

/v2.6/gamer/friends/{domain}/{?status}
  • Parameters
  • domain
    string (required) Example: private

    the domain handling relations

    status
    string (optional) 

    “blacklist” to retrieve the blacklisted gamer’s

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { "friends|blacklisted" : [
        { "<gamer_id_1>" : { displayName : "gamer1", lang : "en" } },
        {"<gamer_id_2>" : { displayName : "gamer2", lang : "fr" } }
    ] }
    

Resources 

/v2.6/gamer/friends/{domain}/{friendid}?{status}
  • Parameters
  • domain
    string (required) Example: private

    the domain handling relations

    friendid
    string (required) 

    a gamer id

    status
    string (required) 

    must be one of [add | forget | blacklist]

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "<gamer_id>" : "<status>"
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    { 
        "code" : "GamerIdNotFound"
    }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "<gamer_id>" : "<status>"
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    { 
        "code" : "StatusNotFound"
    }
    
  • Response  501
  • Headers
    Content-Type: application/json
    Body
    { 
        "code" : "StatusNotSupported"
    }
    

Sponsoring 

God father 

Get sponsoring code
/v2.6/gamer/godfather/{domain}

Obtains a code for sponsoring. The code is different for each game

  • Parameters
  • domain
    string (required) Example: private

    the domain handling relations

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { "godfathercode" : "wSde2dF" }
    
Set godfather
/v2.6/gamer/godfather/{domain}

Set the godfather of the current user and give a reward to the godfather.

  • Parameters
  • domain
    string (required) Example: private

    the domain handling relations

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "godfather": "wSde2dF",
        "maturity" : 100,
        "reward" : {
            transaction : { "gold" : 10},
            description : "this is a reward tx",
            domain : "private"
        }
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "done" : 1,
        "balance" : {},
        "achievements : {}
    }
    
  • Response  438
  • Headers
    Content-Type: application/json
    Body
    { 
        "code" : "alreadyGodchild"
    }
    
Get godfather
/v2.6/gamer/godfather/{domain}

Retreive the godfather of the current user.

  • Parameters
  • domain
    string (required) Example: private

    the domain handling relations

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "<gamer_id>" : "..."
    }
    

Resources 

/v2.6/gamer/godchidren/{domain}

Get every godchildren for the current user.

  • Parameters
  • domain
    string (required) Example: private

    the domain handling relations

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "godchildren" : [ { "gamer_id" : "..."}]
    }
    

Scores and Leaderboards 

Scores

Resources 

/v2.6/gamer/scores/{domain}/{leaderboard}{?order}{&force}

This is not necessarily the highest score, but only the highest is stored.

  • Parameters
  • domain
    string (required) 

    the domain used for this leaderboard

    leaderboard
    string (required) 

    the board where the gamer score in

    order
    string (optional) Default: hightolow 

    the order to sort the board hightolow or lowtohigh

    force
    string (optional) Default: false 

    if true, override any previous score

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "score": 100,
        "info" : "whatever json"
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    { 
        "rank" : 1
    }
    

Resources 

/v2.6/gamer/scores/{domain}/{leaderboard}{?order}{&type}{&page}{&count}
  • Parameters
  • domain
    string (required) 

    the domain used for this leaderboard

    leaderboard
    string (required) 

    the board where the gamer score in

    order
    string (optional) Default: hightolow 

    deprecated, defaults to leaderboard’s ordering

    type
    string (optional) Default: highscore 

    one of ["highscore", “friendscore”]

    page
    number (optional) Default: 1 

    th epage number or a special “me” for centered scores

    count
    number (optional) Default: 10 

    the max returned rows

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "<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: {} } 
                    }
                ]
        }
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "LeaderboardNotFound",
    }  
    
  • Response  402
  • Headers
    Content-Type: application/json
    Body
    {
        "code" : "NoScoreYet",
        "message" : "Asked for centered scores on a gamer who never scores"
    }  
    

Resources 

/v2.6/gamer/bestscores/{domain}

Get all the gamer’s bestscores

  • Parameters
  • domain
    string (required) 

    the domain used for this leaderboard

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "easy" : { score:100, info : "desc" , timestamp : ""}
        "meduim" : { score:20, info : "desc", timestamp : "" }
        "hard" : { score:10, info : "desc", timestamp : "" }
    }
    

Events 

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.

Resources 

/v1/gamer/event/{domain}/{gamer_id}

Send a message

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain

    gamer_id
    string (required) Example: 5402cf700530df4fa7ed3629

    The recepient for the message

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "key": "value",
        "anotherKey" : "another value",
        "data" : [{
            "any": "data"
        }]
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
        {
            "id" : "5cf3baf5-742c-4c3c-ad88-d12d84b01574",
            "key": "value",
            "anotherKey" : "another value",
            "data" : [{
                "any": "data"
            }]
        }
    

Resources 

/v1/gamer/event/{domain}{?ack}{&timeout}

Receive messages

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain

    ack
    string (optional) Default: auto Example: 5cf3baf5-742c-4c3c-ad88-d12d84b01574

    The message ID to acknowledge

    timeout
    integer (optional) Default: 50000 

    The long polling timeout, in milliseconds

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
        {
            "id" : "5cf3baf5-742c-4c3c-ad88-d12d84b01574",
            "key": "value",
            "anotherKey" : "another value",
            "data" : [{
                "any": "data"
            }]
        }
    
  • Response  204

Achievements 

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.

Resources 

/v1/gamer/achievements/{domain}

List 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.

  • Parameters
  • domain
    string (required) Example: private

    The domain, use private to return the default achievemens created for your game in the Front Office

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "achievements": {
            "highScore": {
                "type": "limit",
                "config": {
                    "maxValue": 1000,
                    "unit": "score"
                },
                "gameData": {
                    "initiallyHidden": true
                },
                "gamerData": {
                    "unhidden": true
                },
                "progress": 0.06
            }
        }
    }
    

Custom information about an achievement 

Set custom information about an achievement, for an user
/v1/gamer/achievements/{domain}/{achievement}/gamerdata

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain, use private to return the default achievemens created for your game in the Front Office

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "unhidden": true
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "achievement": {
            "type": "limit",
            "config": {
                "maxValue": 1000,
                "unit": "score"
            },
            "gameData": {
                "initiallyHidden": true
            },
            "gamerData": {
                "unhidden": true
            },
            "progress": 0.06
        }
    }
    
Extract custom information about an achievement
/v1/gamer/achievements/{domain}/{achievement}/gamerdata

Use this API to fetch the custom data associated with a gamer for a given achievement.

  • Parameters
  • domain
    string (required) Example: private

    The domain, use private to return the default achievemens created for your game in the Front Office

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "gamerData": {
            "unhidden": true
        },
    }
    

Matches 

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.

Resources 

/v1/gamer/matches{?domain}

Creates a new match, automatically attached to your gamer ID. Only the maxPlayers node is required.

Description of a match

FieldDescriptionValue
_idstringID of the match, keep it safe to allow for joining it or fetching it later (read only)
creatorstringID of the gamer who created the game (read only)
customPropertiesjsonJSON containing the user properties of the match (only one level, with numbers or strings as values)
domainstringdomain to which the match belongs; used for scoping purposes (read only)
descriptionstringdescription of the game (non localized)
globalStatejsonglobal state of the match, which may be used to reconstruct the game locally (read only)
lastEventIdstringID of the last event, which must be passed by any player who wishes to make a move (read only)
maxPlayersnumbermaximum number of players who can join this game
eventsjsonlist of pending events, cleared whenever a globalState is posted along with a move by one of the players (read only)
playersarraylist of IDs of players participating to the match (read only)
seed31-bit integera random number generated upon match creation, to be used by players
shoearrayan 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.
statusstringeither “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.

  • Parameters
  • domain
    string (required) 

    the domain on which to place the match (use private by default for a domain that is scoped for your game)

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "description": "Sample match for testing",
        "maxPlayers": 3
        "customProperties": {
            "type": "coop"
        },
        "globalState": {
            "startup": "globalState"
        },
        "shoe": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "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"
        }
    }
    

Resources 

/v1/gamer/matches{?domain}{&properties}{&participating}{&finished}{&invited}

Lists the matches available for join, using a query to filter the results.

Filtering by properties

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"}

  • Parameters
  • domain
    string (required) 

    the domain on which to look for matches (use private by default for a domain that is scoped for your game)

    properties
    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.

    participating
     (optional) 

    pass this parameter to only list matches to which you are participating.

    finished
     (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.

    invited
     (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.

    limit
    number (optional) 

    the maximum number of matches to return. Used for pagination. Defaults to 30.

    skip
    number (optional) 

    the index of the first item to return. Used for pagination. Zero-based, defaults to 0.

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "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"
            },
        ]
    }
    

Working with a match 

Fetching in-depth information about a match
/v1/gamer/matches/{match_id}

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.

  • Parameters
  • match_id
    string (required) 

    the ID of the match as previously returned.

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "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"
        }
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "InvalidMatch",
        "message": "The match does not exist",
        "status": 404
    }
    
Deleting a match
/v1/gamer/matches/{match_id}

Deletes a match, erasing it along with its history. You need to be the creator of the match to perform this operation.

  • Parameters
  • match_id
    string (required) 

    the ID of the match to delete.

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "done": 1
    }
    
  • Response  431
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "MatchNotFinished",
        "message": "This match needs to be finished in order to perform this operation"
    }
    

Resources 

/v1/gamer/matches/{id}/join

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.

Events related to matches

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.

  • Request
    • Parameters
      • id (required, string) … the ID of the match to join.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "osn": {"en": "I just joined!", "ja": "tadaima!"}
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "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"
        }
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "InvalidMatch",
        "message": "The match does not exist",
        "status": 404
    }
    
  • Response  431
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "AlreadyJoinedMatch",
        "message": "You are already being part of this match"
    }
    
  • Response  431
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "MaximumNumberOfPlayersReached",
        "message": "This match can not accept any additional player"
    }
    
  • Response  433
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "BadMatchID",
        "message": "This match does not exist or is not active"
    }
    

Resources 

/v1/gamer/matches/{id}/leave

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.

  • Request
    • Parameters
      • match_id (required, string) … the ID of the match to operate on.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "osn": {"en": "Bye bye!", "fi": "Näkemiin!"}
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "match": {
            "_id": "548726461c4158b4c73d43fa",
            "lastEventId": "5487264710de0db4c71fe752",
            "status": "finished"
        }
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "InvalidMatch",
        "message": "The match does not exist",
        "status": 404
    }
    
  • Response  433
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "BadMatchID",
        "message": "This match does not exist or is not active"
    }
    

Resources 

/v1/gamer/matches/{id}/invite/{gamer_id}

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.

  • Request
    • Parameters
      • id (required, string) … the ID of the match to operate on.
      • gamer_id (required, string) … the ID of the gamer to invite on this match.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "osn": {"en": "Please join my super duper game!", "it": "Sei invitato!"}
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "match": {
            "_id": "5488121cebc67955fb8f42e2",
            "lastEventId": "5488121c4d95f055fbadde9a",
            "status": "running"
        }
    }
    
  • Response  431
  • Headers
    Content-Type: application/json
    Body
    {
        "message": "The player is already invited to the match",
        "name": "AlreadyInvitedToMatch"
    }
    
  • Response  433
  • Headers
    Content-Type: application/json
    Body
    {
        "message": "A passed gamer ID is invalid",
        "name": "BadGamerID"
    }
    
  • Response  433
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "BadMatchID",
        "message": "This match does not exist or is not active"
    }
    

Resources 

/v1/gamer/matches/{id}/invitation

Allows to dismiss an invitation to a match. Works for the authenticated gamer and only if the gamer has been invited previously.

  • Request
    • Parameters
      • id (required, string) … the ID of the match to operate on.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "match": {
            "_id": "5488121cebc67955fb8f42e2",
            "lastEventId": "5488121c4d95f055fbadde9a",
            "status": "running"
        }
    }
    
  • Response  433
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "BadMatchID",
        "message": "This match does not exist or is not active"
    }
    

Resources 

/v1/gamer/matches/{id}/move{?lastEventId}

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.

Making moves

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.

  • Request
    • Parameters
      • lastEventId (required, string) … the ID of the last move, as received in the body of the match received when joining, or the value received in the last event. Allows to make sure that you are synchronized with the match before making a move.
      • id (required, string) … the ID of the match to operate on.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "move": {
            "what": "changed"
        },
        "globalState": {
            "full": "game_state"
        },
        "osn": {"en": "It is now your turn!", "de": "Spielen Sie jetzt!"}
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "match": {
            "_id": "548726461c4158b4c73d43fa",
            "lastEventId": "5487264710de0db4c71fe752",
            "status": "finished"
        }
    }
    
  • Response  400
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "MissingParameter",
        "message": "The parameter is invalid or absent: lastEventId",
        "status": 400
    }
    
  • Response  431
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "InvalidLastMoveId",
        "message": "This move ID is invalid, please resynchronize"
    }
    

Resources 

/v1/gamer/matches/{id}/shoe/draw{?count}{&lastEventId}

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.

Working with the shoe

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.

  • Request
    • Parameters
      • lastEventId (required, string) … the ID of the last move, as received in the body of the match received when joining, or the value received in the last event. Allows to make sure that you are synchronized with the match before making a move.
      • count (required, integer) … the number of items to draw from the shoe.
      • id (required, string) … the ID of the match to operate on.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "osn": {"en": "I just drew something from the shoe!", "fr": "J'ai récupéré un objet du sabot!"}
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "drawnItems": [
            {
                "prop4": "value4"
            },
            {
                "prop3": "value3"
            }
        ],
        "match": {
            "_id": "5492a7c6a6725f0000b59e46",
            "lastEventId": "5492a7c7a6725f0000b59e4f",
            "status": "running"
        }
    }
    
  • Response  400
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "MissingParameter",
        "message": "The parameter is invalid or absent: count",
        "status": 400
    }
    
  • Response  431
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "InvalidLastMoveId",
        "message": "This move ID is invalid, please resynchronize"
    }
    

Resources 

/v1/gamer/matches/{id}/finish{?lastEventId}

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.

  • Request
    • Parameters
      • lastEventId (required, string) … the ID of the last move, as received in the body of the match received when joining, or the value received in the last event. Allows to make sure that you are synchronized with the match before making a move.
      • id (required, string) … the ID of the match to operate on.
    Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Authorization: Basic gamer_id:gamer_secret
    Body
    {
        "osn": {"en": "The match is finished.", "es": "El partido ha terminado."}
    }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
    {
        "match": {
            "_id": "548726461c4158b4c73d43fa",
            "lastEventId": "5487264710de0db4c71fe752",
            "status": "finished"
        }
    }
    
  • Response  404
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "InvalidMatch",
        "message": "The match does not exist",
        "status": 404
    }
    
  • Response  433
  • Headers
    Content-Type: application/json
    Body
    {
        "name": "BadMatchID",
        "message": "This match does not exist or is not active"
    }
    

Indexing 

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.

Resources 

/v1/index/{domain}/{indexName}

Index a new object

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain

    indexName
    string (required) Example: matchIndex

    The index Name

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Body
        {
            "_id": '55706319d11b8125d58c8abe',
            "properties": {
                "rank": "captain",
                "age": 28,
                "world": "utopia"
            },
            "payload": {
                "name": "Captain America",
                "lastPlayed": 1433428652427
            }
        }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
        { _index: 'com.clanofthecloud.cloudbuilder.m3nsd85gnqd3',
          _type: 'matchIndex',
          _id: '55706319d11b8125d58c8abe',
          _version: 1,
          created: true
        }
    

Resources 

/v1/index/{domain}/{indexName}/search?{q}&{sort}&{from}&{max}

Search the index

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain

    indexName
    string (required) Example: matchIndex

    The index Name

    q
    string (optional) Example: rank:captain

    The query string

    sort
    string (optional) Example: ["age"]

    a JSON array of properties names for sorting

    from
    int (optional) Example: 0

    The first result index

    max
    int (optional) Example: 10

    The number of results to return

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
  • Response  200
  • Headers
    Content-Type: application/json
    Body
        { 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
                    }
               }
             }
           ]
        }
    
  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret
    Body
        {
            "query": {
                "term": {
                    "rank": "captain"
                }
            }
        }
    
  • Response  200
  • Headers
    Content-Type: application/json
    Body
        { 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
                    }
               }
             }
           ]
        }
    

Resources 

/v1/index/{domain}/{indexName}/{id}

Get an index element

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.

  • Parameters
  • domain
    string (required) Example: private

    The domain

    indexName
    string (required) Example: matchIndex

    The index Name

    id
    string (required) Example: 55706319d11b8125d58c8abe

    The object Id you’re looking for

    Headers
     (required) 
    x-apikey : testgame-key
    x-apisecret : testgame-secret
    
    Body
     (required) 
  • Response  200
  • Headers
    Content-Type: application/json
    Body
        { _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
               }
             }
            }
        }
    

Resources 

/v1/index/{domain}/{indexName}/{id}

Delete an element of the index

When you want to remove an index entry, use this API. If you just want to update an entry, just use POST instead.

  • Parameters
  • domain
    string (required) Example: private

    The domain

    indexName
    string (required) Example: matchIndex

    The index Name

    id
    string (required) Example: 55706319d11b8125d58c8abe

    The object Id you’re looking for

  • Request
  • Headers
    Content-Type: application/json
    x-apikey: testgame-key
    x-apisecret: testgame-secret

Generated by aglio on 28 Jun 2015