Introduction

About

The API of globalstats.io is the most important feature that this platform provides. Because of that we took a lot of effort to keep it as simple and straight forward as possible. All functionality is provided from developers for developers - following the KISS principle, we want to satisfy your needs while keeping integration painless and as easy as possible. In the following sections we will teach you the basics of our API and you will see how easy it is to implement it in any framework or language that you are using.

Libraries

To make it even easier for you to integrate highscores into your game with just a few clicks, we will provide libraries for the most common frameworks and platforms.

Currently we have libraries for following frameworks available on https://github.com/globalstats-io:
We are planing to create libraries for the following:
  • Unreal Engine

Let us know if we miss your favourite platform. Simply drop us a short feedback message with the platform you want to see coming up next here.

Security

Our primary concern while designing the API was security. Thats why we decided to utilize OAuth2 to authenticate and authorize each game session individually and provide a stable foundation for keeping data safe and espically prevent any unauthorized access to data. We will let you know the basics that you need to know to authenticate your game with our API.

Of course we utilize SSL for our Website and API to make sure your data stays secure on the way from your game to our servers.

Rate Limits

To prevent spamming, misuse and brute-force attacks all calls to the API are limited to a maximum of 60 requets per minute. This does also include downloading images via the API. If the rate limit is reached a 503 Service Temporarily Unavailable error will be returned.

There are dedicated limits to some API calls. Those will be pointed out below, but here a summary of them all:
  • /oauth/access_token limited at 6 requests per minute

Access Tokens

How It Works

We use OAuth2 to authenticate your game with our API. OAuth2 defines a lot of functionality to secure HTTP Services. This is best summarized by the first paragraph in the offcial RFC:

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.

So, what does this mean for you? To keep it as simple as possible:
For each game you are able to generate access credentials in the form of a Client ID and a Client Secret. Those keys allow your game to access our API so it is highly recommended that you keep them safe. With those two credentials you can then get a so called Access Token from the API, which allows you to access the API. That Token will expire after one hour. Each of your games, or users, will receive their own token.

Get A Token

To retreive a Access Token simply send a request to our API to https://api.globalstats.io/oauth/access_token that contains your Client ID and Client Secret in the message body.

The HTTP Request looks like this.
POST /oauth/access_token HTTP/1.1
Host: api.globalstats.io
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=endpoint_client&client_id=9bwmMjFjFqxv5PnmHUTsE4PX&client_secret=Q3WzXAw5HhUzQaJRa8UkCzzt

It is important the the grant_type is set to client_credentials and the scope is set to endpoint_client.
When done correctly, the server will respond with the status code 200 and a new Acces Token within the body of the response:
{
  "access_token": "5Znl9s47fDRiUkM9yjDdI88sz66eJEoPj8lwp3h8",
  "token_type": "Bearer",
  "expires_in": 3600
}

This request has a dedicated rate limit. A maximum of 6 requests per minute are allowed.

Statistics

Create new statistics for the first time

With the previously generated Access Token you can now start creating highscores. Make sure that you have your GTD's are set up. If not, head over to your game settings and create the GTD's you want to track.

The first time you push statistics over the API, you have to create them explicitly which is generating a unique ID that will be used for any further updates and pushes of new values. Use following request to create a new statistic for your user:
POST /v1/statistics HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer GnMhV8iAn6VgVD4SmsIMPtLZBSuDfzadoMm17ZhN
Content-Type: application/json
Cache-Control: no-cache

{
    "name":"UserDisplayName",
    "values":
    {
        "highscore":119
    }
}

So, what do those values mean?
First of all you can see the Authorization key added to the Header of the request. This authenticates you with the API.
The name value within the Body of the Request specifies with what name your user will be displayed in the Highscores.
The values themself are the GTD's that you defined in your game configuration. Those consist of a key-value pair.

This step only needs to be done once. It will return following response:
{
  "name": "UserDisplayName",
  "_id": "569c13eb5c25653b008b456d",
  "values": [
    {
      "key": "highscore",
      "value": 119,
      "sorting": "asc",
      "rank": 43
    }
  ],
  "achievements": [
    {
      "key": "fasterthenlight",
      "name": "Faster then light!",
      "description": "You finished the level in under 60 seconds",
      "image_active": "https://api.globalstats.io/images/59a9863f566f427d008b466e",
      "image_inactive": "https://api.globalstats.io/images/59a9863f566f427d008b4670"
    }
  ]
}

The most important value in this response is the _id. It will be used for any future updates for this user. Store it within your game on the users device so you can access it any time you push new values.
Other then that it returns the values that have been pushed into the system and the current ranking this value has in the leaderboard. If you want you can verify if the returned data is the same as you sent, as we may validate and correct invalid values if supplied.

If it happens that a achievement was unlocked with the submit of this score, it will be returned in the achievements part. More on achievements later here

Values and Types

The values provided for each value should be either an integer or a floating point number. This means that everything from "123", "5.4" and even "1.2e3" for a exponent notation are valid numbers. The maximum number possible to store is 92233720368548000 or 9.2233720368548e18. If you require to store larger numbers please let us know here.

Depending on what type you specified for the GTD there are some rules you should know on how you have to format the values in order for them to be displayed correctly within the leaderboard.

Numeric
No special rules here. The number will be displayed as it is.

Time
You have to provide the time in milliseconds. This means to set a time of one second the value has to be set to 1000 which will be displayed in the leaderboard as 0:00:01.000

Currency You have to provide the number as a 1/100th of the currency you want to display. So if you want to display a values of $ 1.00 you have to set the value to 100.

Update existing statistics

This part is where the magic happens. Once you created a Statistic with the previous request, you can now freely push and updated values for this Statistic. As we want to have this process as easy and efficient as possible we do allow relative updates and also allow creating new values within the update request. This means that you only need this one request to manage a users statistic. How does this look like? Well, very easy:
PUT /v1/statistics/569c13eb5c25653b008b456d HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer GnMhV8iAn6VgVD4SmsIMPtLZBSuDfzadoMm17ZhN
Content-Type: application/json
Cache-Control: no-cache

{
    "values":
    {
        "highscore":+20
    }
}

First, lets go over the important values of this request.
Within the URL you specify to which Statistic this update should be applied. This is the _id value that was returned from the create request. So the URL that you are calling looks like this in the above example: https://api.globalstats.io/v1/statistics/569c13eb5c25653b008b456d
Again, the Authorization header is added to authenticate with the API.
Then the values is added, same as for the create request, but now with the difference that you can supply relative values! You can either supply a normal number which will overwrite the one stored in our system if it would improve the users ranking for this value, or you supply one of the following relative updates:

  • ++ : This increments the stored value by 1
  • -- : This decrements the stored value by 1
  • +VAL : This increments the stored value by the given VAL
  • -VAL : This decrements the stored value by the given VAL
  • !VAL : Sets the stored value to the given VAL
  • VAL : Sets the stored value to the given VAL if it improves the rank

The incremental updates can be very efficient and usefull if you want to track things like total play time, number of tries for a leve, shots fired, etc.

If it the updated statistic triggered an Achievement, it will be returned in the same format as when you create a new one. More on achievements later here

Display your statistics

Of course we provide you with a way of displaying the current ranking of a user. You can retreive the current ranking with following request:
GET /v1/statistics/569c13eb5c25653b008b456d HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer GnMhV8iAn6VgVD4SmsIMPtLZBSuDfzadoMm17ZhN
Content-Type: application/json
Cache-Control: no-cache

Nothing more. No Body needed. Same as before, the _id is used within the URL to specify the Statistic you want to access and the Authorization header is supplied to authenticate yourself with the API.
This will return following response:
{
  "name": "UserDisplayName",
  "statistics": [
    {
      "key": "highscore",
      "value": 139,
      "sorting": "asc",
      "rank": 43,
      "updated_at": "2016-01-17 22:21:31"
    }
  ]
}

It returns the name of the user and an array of statistics which consist of following values:
  • key : Is the name of the specific statistic value, as it is configured for your application
  • value : Is the current value that is stored for this key
  • rank : Is the position of the player in our global highscore
The array will contain the details for all configured statistic values for which a value has already been pushed to our system.

Get a Statistic Section

A more advanced way of displaying the ranking of the current user in your game is by using a statistic section. The section contains the current ranking of the user and also the rank of the 5 players that are better and worse then the player.
GET /v1/statistics/569c13eb5c25653b008b456d/section/score HTTP/1.1
Host: 127.0.0.1:81
Authorization: Bearer wI2DIVAIPoEH3MUhJkQzZRlf9L5m1JmjxsJBQPjW
Content-Type: application/json
Cache-Control: no-cache

Nothing more. No Body needed. Same as before, the _id is used within the URL to specify the Statistic you want to access and the Authorization header is supplied to authenticate yourself with the API. You also have to supply the GTD Key, in this case score so that the ranks can be calculated.

This will return following response:
{
   "better_ranks":{
      "data":[
         {
            "name":"A better player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/5869300f566f4237008b4773",
            "user_icon":"https:\/\/api.globalstats.io\/images\/5869300f566f4237008b476f",
            "rank":5,
            "value":900
         },
         {
            "name":"Another better player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693011566f4237008b480c",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693011566f4237008b4808",
            "rank":6,
            "value":850
         },
         {
            "name":"Also a good player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/5869300f566f4237008b477c",
            "user_icon":"https:\/\/api.globalstats.io\/images\/5869300f566f4237008b4778",
            "rank":7,
            "value":800
         },
         {
            "name":"Just a player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/5869300e566f4237008b46ec",
            "user_icon":"https:\/\/api.globalstats.io\/images\/5869300e566f4237008b46e8",
            "rank":8,
            "value":750
         },
         {
            "name":"A good player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693012566f4237008b485d",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693012566f4237008b4859",
            "rank":9,
            "value":700
         }
      ]
   },
   "user_rank":{
      "name":"The current player",
      "user_profile":"https:\/\/globalstats.io\/profiles\/5869300c566f4237008b464a",
      "user_icon":"https:\/\/api.globalstats.io\/images\/5869300c566f4237008b4646",
      "value":650,
      "rank":10
   },
   "worse_ranks":{
      "data":[
         {
            "name":"Not such a good palyer",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693012566f4237008b485d",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693012566f4237008b4859",
            "rank":11,
            "value":600
         },
         {
            "name":"A bad player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693012566f4237008b484b",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693012566f4237008b4847",
            "rank":12,
            "value":550
         },
         {
            "name":"Yet another player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693019566f4237008b4a55",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693019566f4237008b4a51",
            "rank":13,
            "value":500
         },
         {
            "name":"A very bad player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693014566f4237008b48c9",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693014566f4237008b48c5",
            "rank":14,
            "value":450
         },
         {
            "name":"The worst player",
            "user_profile":"https:\/\/globalstats.io\/profiles\/58693013566f4237008b48c0",
            "user_icon":"https:\/\/api.globalstats.io\/images\/58693013566f4237008b48bc",
            "rank":15,
            "value":400
         }
      ]
   }
}

It returns the reuqested player and arrays with the 10 players that are closest to the player in the leaderboard:
  • better_ranks : The 5 players that are above the given player in the leaderboard
  • user_rank : The current player for which the data was requested
  • worse_ranks : The 5 players that are below the given player in the leaderboard
The data for each of the players is defined as follows:
  • name : Simply the name of the Player, as it is displayed on the Leaderboard on our platform
  • user_profile : The URL to the users Profile on our platform
  • user_icon : The URL to fetch the icon for this user
  • rank : Is the position of the player in our global highscore
  • value : Is the score for this GTD of the player in our global highscore

Display a Leaderboard

At last, you can also fetch the current top positions of your leaderboard with a GTD of your choice. You can retreive that leaderboard with following request:
POST /v1/gtdleaderboard/score HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer GcOQYilwxyxjqE68ciptpuqppcd0IsIN671us1ml
Content-Type: application/json
Cache-Control: no-cache

{
    "limit":2,
    "additionals": [
        "shots",
        "time"
        ]
}

Within the URL you specify the GTD for which the leaderboard should be returned. In this case we want the leaderboard of the GTD score. You also have to supply the number of players you want to fetch. This must be a number between 1 and 100.
Optionally you can supply an array with additionals which can be used to add other GTD values to the response. This does not effect the sorting, it only adds them to the response as additional object. If not supplied, the object will not exist in the response.

This will return following response:
{
   "data":[
      {
         "name":"Raptorfx",
         "user_profile":"https:\/\/globalstats.io\/profiles\/578744d07ca5a826008b4925",
         "user_icon":"https:\/\/api.globalstats.io\/images\/578744d07ca5a826008b4921",
         "rank":1,
         "value":1,
         "additionals":[  
            {  
               "key":"shots",
               "value":577,
               "rank":12
            },
            {  
               "key":"time",
               "value":137000,
               "rank":13
            }
         ]
      },
      {
         "name":"a1rwulf",
         "user_profile":"https:\/\/globalstats.io\/profiles\/578744d67ca5a826008b4a8d",
         "user_icon":"https:\/\/api.globalstats.io\/images\/578744d67ca5a826008b4a89",
         "rank":1,
         "value":1,
         "additionals":[  
            {  
               "key":"shots",
               "value":412,
               "rank":15
            },
            {  
               "key":"time",
               "value":99000,
               "rank":16
            }
         ]
      }
   ]
}

It returns a data array containing objects for each player. The player objects consist of following values:
  • name : Simply the name of the Player, as it is displayed on the Leaderboard on our platform
  • user_profile : The URL to the users Profile on our platform
  • user_icon : The URL to fetch the icon for this user
  • rank : Is the position of the player in our global highscore
  • value : Is the score for this GTD of the player in our global highscore

Achievements

Get all Achievements

One of the awesome features we offer are Achievements. We do not think that it needs to be explained what they are, so let's just jump straigt into how to use them.

After you have created some achievements for your game, you can easily get all of them directly via the API. This request is usefull if you want to display a Overview of all Achievements. Just send this simple request at any time you like:
GET /v1/achievements HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer KDoPLs7Q7IhEfj9joz23qMqUJVhZTAVLOgNF8Ifp
Content-Type: application/json
Cache-Control: no-cache

It returns an array of achievements.
{
    "achievements": [
        {
            "key": "fasterthenlight",
            "name": "Faster then light!",
            "description": "You finished the level in under 60 seconds",
            "image_active": "https://api.globalstats.io/images/59a9863f566f427d008b466e",
            "image_inactive": "https://api.globalstats.io/images/59a9863f566f427d008b4670"
        },
        {
            "key": "first",
            "name": "First Achievement",
            "description": "You started playing our game. Awesome!",
            "image_active": "https://api.globalstats.io/images/59a98b74566f427d008b4690",
            "image_inactive": "https://api.globalstats.io/images/59a98b74566f427d008b4692"
        }
    ]
}

What are the values? A short overview:
  • key : The key of the achievement. It is used for all further interactions with the achievement via the API
  • name : The name of the achievement as it should be displayed to the user
  • description : A description of how this achievement can be accomplished
  • image_active : The image that the user will see when he accomplished this achievemend
  • image_inactive : The image the user will see when he has not yet accomplished this achievement

Very easy, right?

Manual Accomplishments

There are two ways for a user to accomplish an achievement.

Automatically via a Trigger, which will result in the achievements beeing returned in the store or updated function when the conditions are met
Manually via this request below. This can be used to accomplish an achievement for example at a specific point in the game like when a boss was beaten.

The request looks as follows:
GET /v1/statistics/59a98824566f421b008b4693/achievements/fasterthenlight/accomplish HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer KDoPLs7Q7IhEfj9joz23qMqUJVhZTAVLOgNF8Ifp
Content-Type: application/json
Cache-Control: no-cache

There are two values passed in this request:
  • id : The id of the statistic that was created here or retreived via one of the many requests. In this case 59a98824566f421b008b4693.
  • key : The key of the achievement. In this case fasterthenlight

As a response, the achievement will be returned.
{
    "achievement": {
        "key": "fasterthenlight",
        "name": "Faster then light!",
        "description": "You finished the level in under 60 seconds",
        "image_active": "https://api.globalstats.io/images/59a9863f566f427d008b466e",
        "image_inactive": "https://api.globalstats.io/images/59a9863f566f427d008b4670"
    }
}

Important: If the achievement is already accomplished, this call will return with a status code of 403 with the error message:
{
    "code": 403,
    "message": "forbidden",
    "data": "Achievement already accomplished"
}


Get the users Achievements

Of course it is also possible to display the achievements in a more customized way to the user. This call will return the achivements in the same way as Get all Achievements but will include a flag if the achievement is already accomplished by the user.

The request looks like this:
GET /v1/statistics/59a98824566f421b008b4693/achievements HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer KDoPLs7Q7IhEfj9joz23qMqUJVhZTAVLOgNF8Ifp
Content-Type: application/json
Cache-Control: no-cache

Again, the argument supplied in the URL is the id of the statistic.

This results in following response:
{
    "achievements": [
        {
            "key": "fasterthenlight",
            "name": "Faster then light!",
            "description": "You finished the level in under 60 seconds",
            "image_active": "https://api.globalstats.io/images/59a9863f566f427d008b466e",
            "image_inactive": "https://api.globalstats.io/images/59a9863f566f427d008b4670",
            "accomplished": true
        },
        {
            "key": "first",
            "name": "First Achievement",
            "description": "You started playing our game. Awesome!",
            "image_active": "https://api.globalstats.io/images/59a98b74566f427d008b4690",
            "image_inactive": "https://api.globalstats.io/images/59a98b74566f427d008b4692",
            "accomplished": false
        }
    ]
}

Linking

How it works

Linking is one of the core components that make this platform unique. It allows your users to link the statistics you create to their own account. By that they are visilbe on the Leaderboards with their account, able to track their progress within their profile and share it with their friends. We highly recommend that you prompt your users to link their statistics with their account. Best checkout one of our Sample Games to see how you can achieve this in your game.

Request Linking

Requesting data for linking is very easy. After you have created the statistics and have the _id at hand in your game, simply make another call to our API with just this ID. If you want, you can also provide the email address of the user and we will automatically send the user the linking details per mail. Or you can just display the Pin to the user in your game.
In general we recommend that you provide a link that the user can click on directly if you are able to open up a web browser.
If you can't open a browser, we recommend that you prompt the user for his email address and supply it so that we can send him an email diretly.
If you are on a game console where text input is not that easy, we recommend that you display the Pin to the user with the URL to this website.

The Request for a Link looks like this:
POST /v1/statisticlinks/5714a86bedb6af1b008b45b7/request HTTP/1.1
Host: api.globalstats.io
Authorization: Bearer pTQRFQGDsvyRZ0y3o91GtstosGrowhuA3YLnIXmA
Content-Type: application/json
Cache-Control: no-cache

{
    "email":"feedback@globalstats.io"
}

In return you will receive following data from the API:
{
    "url": "https:\/\/globalstats.io\/statisticlinks\/qqUrmK1E4t0bJqLlWqiw8xMK3ENFIKw9bqAxbCbf\/link",
    "pin": "24862156"
}

Important Note
The Link and the Pin are only valid for one hour after requesting it. If you want to display it to the user again you can simply request another link.

Error Handling

Return Codes

For returning errors we use the already existing and easy to use HTTP Error Codes so we can point you in the right direction on what is going wrong. Following codes are used in general for reporting issues:
  • 400 : Bad Request, returned when the OAuth Token is not valid
  • 403 : Forbidden, you are not allowed to access the resource
  • 404 : Not Found, you tried to fetch data where there is none
  • 405 : Method not allowed, you are not allowed to access this feature
  • 503 : Rate Limit reached

Feedback and future Features

We are always improving our API and trying to match the needs of todays Game Developers. If you feel that something is designed too difficult or that a important feature is missing, please, use our Feedback Form to let us know of how we can improve your experience.