API specification

Introduction

KWS provides a set of HTTP APIs that can be used as an interface to create kid-safe apps, by providing services like the following:

  • User authentication with the OAuth single sign-on.
  • Request parent permissions and get user data if permission is granted.
  • Trigger user actions like for example awarding points or inviting friends.
  • Get application related data for features like leaderboards and user maps.
  • etc…

Note

All KWS APIs use https protocol and JSON

HTTP Response code convention

KWS APIs follow HTTP standard convention. A successful API call will return a 20x code while the following convention has been adopted for HTTP error codes:

  • 400 Invalid data in body or query
  • 401 Authentication error (token does not exist or has expired, or error trying to get the token)
  • 403 The action is not allowed (no permission, or also when an event has been triggered the maximum times, etc)
  • 404 Resource not found
  • 405 Method not allowed
  • 409 The operation cannot be performed for any reason (missing necessary data, conflict, etc.)
  • 500 Unexpected error

API Authentication

All the endpoints will need a Bearer token in the HTTP Authorization header like this:

Authorization: Bearer token

Where token has to be replaced by the corresponding session token obtained in the OAuth authentication process. The token will have different permissions and will enable calling different endpoints depending on the client and the type of credentials used in the authentication flow. This is further explained in the next section: OAuth

OAuth Authentication

KWS follows OAuth2 core standard. In order to know about the basics of OAuth2, like understanding the different flows and the concept of scopes, please visit the following site: https://oauth.net/2/. The authorization flows that are supported are the following:

  • Client credentials flow: used in Backend to Backend interactions.
  • Authorization code flow: used to authenticate users with the single sign-on for websites.
  • Implicit flow: used to authenticate users with the single sign-on for mobile apps and websites without backend.

Note

After a bearer token has expired, using it in API call will result in a 401 error. It is the reponsibility of the application to handle this by renewing the token in advance or by catching the 401 error, and retrying the API call after getting a new valid token.

The bearer token

KWS bearer token uses the JSON Web Token standard (see https://jwt.io/). This is an example of a valid token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhcHBJZCI6MzU1LCJjbGllbnRJZCI6InBvcGphbS1hc2VhbiIsInNjb3BlIjoiYXBwIiwiaWF0IjoxNTAxNzcxNjk4LCJleHAiOjE1MDE4NTgwOTgsImlzcyI6InN1cGVyYXdlc29tZSJ9.TsjuG3MWV-e8bHbk7bGNOSQqqsb-zeHxLQG5TuNcbAs

As shown in the example, and according to the specification, the JSON web token is formed by 3 parts that are separeted by dots. The part in the middle is the payload of the token and it contains some data that is useful for the application, like the app id and/or the user id that have to be used as url parameters in the API calls. As defined in the standard, this payload is not encrypted and can be read from the application. In order to get the data from the payload, the only step needed is to base64 decode it. As an example, javascript code that obtains the payload data is shown next:

function getPayloadDataFromToken(token) {
    let payLoadData = null;
    try {
        let parts = token.split(':');
        payloadData = atob(parts[1]);
    } catch (e) {
        // invalid token. could not parse payload data
    }
    return payloadData;
}

For example, this is the payload data for the given example token:

{
    "appId": 355,
    "clientId": "popjam-asean",
    "scope": "app",
    "iat": 1501771698,
    "exp": 1501858098,
    "iss": "superawesome"
}

Scopes

The available scopes for an authentication token are the following:

  • app: Scope that allows to get and update all the data that the application can access to, including the data of its users for which the app has permission. It must be used in Backend to Backend API calls only and never exposed to any frontend.
  • frontend: Scope that allows to get data that can be shown to anonymous users, like for example leaderboards. Tokens with this scope can be used by frontends as the name suggests.
  • user: Scope that is specific to a user and that allows to read and write data for that specific user. This token is received only after user authentication and is normally used in frontends.

Client credentials

This flow is used when a Backend wants to use KWS API directly. The available scopes are app and frontend.

Important

This authentication flow must never be done from a frontend directly. The backend could however expose the received token to the frontend only in the case that the scope is frontend. In other words, the default app scope must never be used in frontends.

Example request:

POST /oauth/token HTTP/1.1
Host: examplekwsapihost.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic examplebase64encodedcredentials

grant_type=client_credentials

Example response:

Content-Type: application/json

{
    "token_type": "bearer",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhcHBJZCI6MzU1LCJjbGllbnRJZCI6InBvcGphbS1hc2VhbiIsInNjb3BlIjoiYXBwIiwiaWF0IjoxNTAxNzcxNjk4LCJleHAiOjE1MDE4NTgwOTgsImlzcyI6InN1cGVyYXdlc29tZSJ9.TsjuG3MWV-e8bHbk7bGNOSQqqsb-zeHxLQG5TuNcbAs",
    "expires_in": 86400
}

Request Headers:

Header Parameter Value Description
Host examplekwsapihost.com Hostname of KWS for the app (provided by KWS)
Accept application/json Expected format of response
Content-Type application/x-www-form-urlencoded Type of content of body as defined in OAUTH2 standard for this call
Authorization Basic examplebase64encodedcredentials HTTP Basic Auth header with client id and client secret as credentials

Request Body fields:

Body Parameter Required Meaning
grant_type yes Type of auth flow. In this case the value must be client_credentials
scope no Requested scope for the token. If omited app scope is received by default

Response Body fields:

Body Parameter Required Meaning
token_type yes Type of the token. In this call it will always be bearer
access_token yes The access token to be used in the API
expires_in yes Time until expiration of the token in seconds

As shown in the example, and in order to follow OAuth2 specification, the body in this call is sent with form urlencoded format, as opposed to the API, where JSON is always used. The response is however in JSON as also defined in the standard.

The authorization header in this case corresponds to an HTTP Basic authentication where the username is the client id and the password is the client secret that were obtained when registering the app in KWS (see Getting started section for hints where to get the app credentials and see https://tools.ietf.org/html/rfc2617 for more info about HTTP basic authentication standard).

Authorization code flow

This flow is used when a user wants to sign in the web app. The user has to be redirected to the single sign on website, where they will provide their credentials in order to sign in and then, they will be redirected back to the application. The process can be summed up with the following steps:

  1. The web application detects that the user is not logged in and displays a log in button that links to the single sign on.
  2. The user enters their credentials in the single sign on website.
  3. KWS redirects the user to a callback url in the original application providing an authorization code.
  4. The backend of the application makes a call to KWS to exchange that authorization code for a token with user scope and redirects the user to the website, where in this case the user is authenticated and the generated token can be used to make the necessary API calls.
  5. The app website can optionally store the token by any of the available means (like local storage) so that the session is kept for the next time the user comes back to the app.

Redirecting the user to the single sign-on In order to redirect the user to the single sign-on, apart from the url link itself some parameters have to be sent like in the following URL:

https://examplekwsclub.com/oauth?clientId=yourClientId&redirectUri=https://example.com/oauthCallback&state=optionalValue&language=en

Where examplekwsclub.com must be replaced with the corresponding single sign-on website domain that is provided by KWS. The different query parameters of this url are explained in the next table

Single sign-on URL query parameters:

Body Parameter Required Meaning
clientId yes The clientId of the application (can be seen in KWS control panel)
redirectUri yes The callback uri that the user will be redirected to with the authorisation code
state no A value that will be passed back later to the redirected uri
language no ISO-639-2 language code for the single sign-on web. English by default

Note

The redirection uri must be added in the app Integration settings in KWS control panel so that it can be accepted

After the user signs in, they will be redirected to the redirectUri as explained in the next step

Getting the authorization code and exchanging it for a token

The user has signed in and has been redirected to the callback url, that looks like this:

https://example.com/oauthCallback?state=optionalValue&code=authorizationCodeExampleValue

OAuth callback query parameters:

Body Parameter Required Meaning
state no The value that was optionally previously passed to the single sign-on url
code yes A code that will be used by the application Backend in order to exchange it for an access token

**Exchanging authorization code for access token **

Important

This part of the process must be done in the backend. After that, the obtained access token can be passed to the frontend.

The final step in this flow is to exchange the authorization code for an access token from the Backend, like explained below:

Example request:

POST /oauth/token HTTP/1.1
Host: examplekwsapihost.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Basic examplebase64encodedcredentials

grant_type: authorization_code
code: authorizationCodeExampleValue
redirectUri: https://example.com/oauthCallback

Example response:

Content-Type: application/json

{
    "token_type": "bearer",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhcHBJZCI6MzU1LCJjbGllbnRJZCI6InBvcGphbS1hc2VhbiIsInNjb3BlIjoiYXBwIiwiaWF0IjoxNTAxNzcxNjk4LCJleHAiOjE1MDE4NTgwOTgsImlzcyI6InN1cGVyYXdlc29tZSJ9.TsjuG3MWV-e8bHbk7bGNOSQqqsb-zeHxLQG5TuNcbAs",
    "expires_in": 86400
}

Request Headers:

Header Parameter Value Description
Host examplekwsapihost.com Hostname of KWS for the app (provided by KWS)
Accept application/json Expected format of response
Content-Type application/x-www-form-urlencoded Type of content of body as defined in OAUTH2 standard for this call
Authorization Basic examplebase64encodedcredentials HTTP Basic Auth header with client id and client secret as credentials

Request Body fields:

Body Parameter Required Meaning
grant_type yes Type of auth flow. In this case the value must be this
code yes This is the value that was passed to the auth callback as a query parameter named code
redirectUri yes The oauth callback redirection uri (it must match the same that was used in previos steps)

Response Body fields:

Body Parameter Required Meaning
token_type yes Type of the token. In this call it will always be bearer
access_token yes The access token to be used in the API
expires_in yes Time until expiration of the token in seconds

At this point, the OAuth authentication flow would be finished and the access token could be used in both backend and frontend.

Implicit flow

This flow is very similar to the Authentication Code flow, and it can be used when the application does not have a backend or also optionally to simplify the flow in certain cases if necessary, like eventually in native mobile applications. The process can be summed up with the following steps:

  1. The web application detects that the user is not logged in and displays a log in button that links to the single sign on.
  2. The user enters their credentials in the single sign on website.
  3. KWS redirects the user to a callback url in the original application providing an access token with user scope.
  4. The app can now use the token given in the callback url to authenticate the user in the API.

Note

The default and recommended flow for user authentication is the Authorization Code. If the app has to use the Implicit flow instead, this has to be activated in the Integration seection of the KWS control panel.

Redirecting the user to the single sign-on In order to redirect the user to the single sign-on, apart from the url link itself some parameters have to be sent like in the following URL:

https://examplekwsclub.com/oauth?clientId=yourClientId&redirectUri=https://example.com/oauthCallback&state=optionalValue&language=en

Where examplekwsclub.com must be replaced with the corresponding single sign-on website domain that is provided by KWS. The different query parameters of this url are explained in the next table

Single sign-on URL query parameters:

Body Parameter Required Meaning
clientId yes The clientId of the application (can be seen in KWS control panel)
redirectUri yes The callback uri that the user will be redirected to with the authorisation code
state no A value that will be passed back later to the redirected uri
language no ISO-639-2 language code for the single sign-on web. English by default

Note

The redirection uri must be added in the app Integration settings in KWS control panel so that it can be accepted

After the user signs in, they will be redirected to the redirectUri as explained in the next step

Getting the token

The user has signed in and has been redirected to the callback url, that looks like this:

https://example.com/oauthCallback?state=optionalValue#token=exampleTokenValue

Note

The token is passed to the redirection Uri as an anchor in this case, so that it is only available in the frontend.

OAuth callback url params:

Body Parameter Required Meaning
state no The value that was optionally previously passed to the single sign-on url
token yes The access token to be used in the API. It is passed as an anchor an not as query parameter

From this point the frontend can start using the token to make API calls.

Frontend API

The API calls listed in this section are available for authenticated users. In other words, the access token needed has to be obtained by one of the user authentication methods explained in the previous subsection. In some cases, as it will be indicated, the call can be also made for anonymous users. In that case, an access token with frontend scope should be used.

In the API urls, any variable id will be enclosed in brackets, like for example {userId}, {appId}, etc., which correspond to the id of the user and the id of the application.

Note

The id of the user and the id of the app can be obtained from the access token (more info here 05-api-spec.html#the-bearer-token) Please note that the appId is a number and differs from the clientId in OAuth

Important

Please note that some of the API calls are from API version 1 and are prefixed by v1 in the url path, while other have been substituted by the next version and are prefixed by v2.

Get Leaderboard

This function allows you to get a leaderboard for the app. It can be filtered by date, including day, week and month leaderboards for example. The user does not have to be authenticated in order to make this call.

  • API call
GET /v1/apps/{appId}/leaders
  • Parameters:

    • offset (number|optional) offset of the leaderboard results (for the paged results. 0 by default)
    • limit (number|optional) limit of the leaderboard results (for the paged results. 0 by default)
    • start (number|optional) lower threshold timestamp (ms) for the date filter
    • end (number|optional) upper threshold timestamp (ms) for the date filter
  • Response:

    • offset (number) offset of the results
    • limit (number) limit length applied to the results
    • count (number) number of total users (if limit were not applied)
    • results (array) paged results. Every entry is an object with the following attributes:
      • results.rank (number) rank of the user
  • Response example

{
        "offset": 0,
        "limit": 50,
        "count": 2,
        "results": [{
                "rank": 1,
                "score": 4386,
                "user": "user321"
        }, {
                "rank": 2,
                "score": 1235,
                "user": "user132"
        }]
}

Generate random display name

This endpoint returns a randomly generated display name based on the nouns and adjectives set for the app’s display names. This display name at the time of the response will not be in use by any other user across the instance of the API. If there are no words set for the current language option, it will fall back to English and attempt to return an English display name.

  • API call
GET /v2/apps/{appId}/randomDisplayName
  • Response:

    • **** (string) A random display name that can be displayed to the user and used for the account creation and/or app activation.
  • Response example

"AwesomeNinja8312"

Has device token

This function checks if the user has a device token registered for this app

  • API call
GET /v1/apps/{appId}/users/hasDeviceToken
  • Response example
true

Get User Profile

This function allows you to get the user’s profile and its app related data

  • API call
GET /v2/apps/{appId}/users/{userId}
  • Response:

    • id (number) id of the user.
    • username (string) specific display name for the app (it is app specific for every user).
    • dateOfBirth (string YYYY-MM-DD)
    • language (string) ISO 639-1 code.
    • permissions (object) list of permissions to access data. Each attribute will be a boolean indicating permission to access every specific piece of data of the child.
    • firstName (string|optional) This field will only be available if the corresponding permission is allowed.
    • lastName (string|optional) This field will only be available if the corresponding permission is allowed.
    • email (string|optional) This field will only be available if the corresponding permission is allowed.
    • streetAddress (string|optional) This field will only be available if the corresponding permission is allowed.
    • postCode (string|optional) This field will only be available if the corresponding permission is allowed.
    • city (string|optional) This field will only be available if the corresponding permission is allowed.
    • country (string|optional) This field will only be available if the corresponding permission is allowed.
    • parentEmail (string|optional) This field will only be available calling from the session of a user
  • Response example

{
        "id": 1,
        "firstName": "User1",
        "lastName": "Test1",
        "email": "testuser1@test.com",
        "dateOfBirth": "2010-01-01",
        "streetAddress": "Street1",
        "city": "City1",
        "postalCode": "N1 000",
        "country": "gb",
        "username": "testuser1DisplayName2",
        "permissions": {
                "accessAddress": true,
                "accessFirstName": true,
                "accessLastName": true,
                "accessEmail": true,
                "accessStreetAddress": true,
                "accessCity": true,
                "accessPostalCode": true,
                "accessCountry": true,
                "sendPushNotification": null,
                "sendNewsletter": null,
                "enterCompetitions": null
        },
        "appData": [{
                "name": "test-appdata",
                "value": 5
        }]
}

Get App Data

This function allows you to retrieve previous stored data related to the user in that specific app. The data is in the form of pair key-values. It can be filtered by key name.

  • API call
GET /v1/apps/{appId}/users/{userId}/appData
  • Parameters:

    • offset (number|optional) offset of the data results (for the paged results. 0 by default)
    • limit (number|optional) limit of the data results (for the paged results. 0 by default)
    • name (number|optional) search a value by that specific key name
  • Response:

    • offset (number) offset of the results
    • limit (number) limit length applied to the results
    • count (number) number of total variables (if limit were not applied)
    • results (array) paged results. Every entry is an object with the following attributes:
      • results.name (string) variable name
      • results.value (number) variable value
  • Response example

{
        "offset": 0,
        "limit": 50,
        "count": 1,
        "results": [{
                "name": "timeTillEnd",
                "value": 2864212
        }]
}

Delete App Data

This function allows you to delete data related to the user in that specific app.

  • API call
POST /v1/apps/{appId}/users/{userId}/appData/deleteByName
  • Parameters:

    • name (string|optional) key name of data you want to delete

Set App Data

This function allows you to create or update data related to the user in that specific app. The data is in the form of pair key-values. Values can only be integers.

  • API call
POST /v1/apps/{appId}/users/{userId}/appData/set
  • Parameters:

    • name (number|optional) key name
    • value (number|optional) value to be stored

Get User points in App

This function allows you to retrieve the user points break down per currency in your app

  • API call
GET /v2/apps/{appId}/users/{userId}/points
  • Response:

    • total (number) Total amount of points breakdown per current the user has available in your app at the moment
    • pending (number) Total amount of points breakdown per the user has blocked due to some transaction in progress
    • totalreceived (number) Total amount of points breakdown per the user received by you app
  • Response example

{
        "total": [{
                "sum": 20,
                "currencyId": 2,
                "singularName": "Awesome point",
                "pluralName": "Awesome points"
        }, {
                "sum": 13,
                "currencyId": 3,
                "singularName": "Other point",
                "pluralName": "Other points"
        }],
        "pending": [{
                "sum": 15,
                "currencyId": 3,
                "singularName": "Other point",
                "pluralName": "Other points"
        }],
        "totalReceived": [{
                "sum": 20,
                "currencyId": 2,
                "singularName": "Other point",
                "pluralName": "Other points"
        }, {
                "sum": 25,
                "currencyId": 3,
                "singularName": "Other point",
                "pluralName": "Other points"
        }]
}

Get User score

This function allows you to retrieve the user score for an app and a currency. You can also specify a time interval

  • API call
GET /v2/apps/{appId}/users/{userId}/score
  • Parameters:

    • start (timestamp) the start date to use for the interval. If left empty it will take everything from the begining
    • end (timestamp) the end date to use for the interval. If left empty it will take everything until today
    • currencyId (integer) The currency ID to use. If left empty it will use the default currency ID
  • Response:

    • score (number) Total amount of points the user has for the specified currency (or default one) and the specified time interval (or overall)
    • rank (number) The current rank of the user for the specified currency (or default one) and the specified time interval (or overall)
  • Response example

{
        "score": 1234,
        "rank": 567
}

Get age gate info

This function allows you to get the age threshold for a user or for a given country, returning a flag indicating if the user is under age. It does not require authentication.

  • API call
GET /v1/countries/childAge
  • Parameters:

    • dob (string|optional) date of bith of the user in the following FORMAT: YYYY-MM-DD.
    • country (string|optional) country of the user. If not provided, it will be detected from requesting IP (to use in Frontend only)
  • Response:

    • country (string) detected country by IP or sent country in API request
    • consentAgeForCountry (number) threshold age
    • age (number|optional) age of the user. Only sent if dob was provided in the request
    • isMinor (boolean|optional) flag indicating if user is under age. Only sent if dob was provided in the request
  • Response example

{
        country: 'US',
        consentAgeForCountry: 13,
        age: 11,
        isMinor: true
}

Update User Profile

This function allows apps to update the application profile of the user (excluding the display name, which is inmutable)

  • API call
PUT /v1/users/{userId}
  • Parameters:

    • firstName (string|optional) This field will only be available if the corresponding permission is allowed.
    • lastName (string|optional) This field will only be available if the corresponding permission is allowed.
    • language (string) ISO 639-1 code.
    • email (string|optional) This field will only be available if the corresponding permission is allowed.
    • address (object|optional) This field will only be available if the corresponding permission is allowed. It would contain the following fields
      • address.street (string)
      • address.postCode (string)
      • address.city (string)
      • address.countryCode (string) if the address.countryCode is set address.country is not allowed
      • address.country (string) DEPRECATED! if the address.country is set address.countryCode is not allowed

Check if event has been triggered

This function is used to check if an event has already reached the limit for the user, and thus will not award points anymore.

  • API call
POST /v1/users/{userId}/hasTriggeredEvent
  • Parameters:

    • eventId (number) event identifier.
  • Response:

    • hasTriggeredEvent (boolean) It will indicate if the event has reached the limit or not.
  • Response example

{
        "hasTriggeredEvent": false
}

Invite a Friend

This function allows a user to invite a friend to the app by providing their email. The user making the invite will get rewarded with points when the new user joins the app.

  • API call
POST /v1/users/{userId}/inviteUser
  • Parameters:

    • email (string) email of the user’s friend.

Get User global points

This function allows you to get the global amount of points break down per currency of a user across all your apps.

  • API call
GET /v2/users/{userId}/points
  • Response:

    • total (number) Total amount of points breakdown per current the user has available in your app at the moment
    • pending (number) Total amount of points breakdown per the user has blocked due to some transaction in progress
    • totalreceived (number) Total amount of points breakdown per the user received by you app If total and pending are subtracted from it, you’ll get the points the user has already spent.
  • Response example

{
        "total": [{
                "sum": 20,
                "currencyId": 2,
                "singularName": "Awesome point",
                "pluralName": "Awesome points"
        }, {
                "sum": 13,
                "currencyId": 3,
                "singularName": "Other point",
                "pluralName": "Other points"
        }],
        "pending": [{
                "sum": 15,
                "currencyId": 3,
                "singularName": "Other point",
                "pluralName": "Other points"
        }],
        "totalReceived": [{
                "sum": 20,
                "currencyId": 2,
                "singularName": "Other point",
                "pluralName": "Other points"
        }, {
                "sum": 25,
                "currencyId": 3,
                "singularName": "Other point",
                "pluralName": "Other points"
        }]
}

Request Permissions

This function allows your app to send a notification to a user’s parent to request permission for a specific feature, like sending a welcome pack or a birthday email.

  • API call
POST /v1/users/{userId}/requestPermissions
  • Parameters:

    • permissions (array) array with the requested permissions. It can include the following strings:
      • permissions.accessEmail (string)
      • permissions.accessAddress (string)
      • permissions.accessFirstName (string)
      • permissions.accessLastName (string)
      • permissions.sendPushNotification (string)
      • permissions.sendNewsletter (string)

Trigger event

This function allows your app to award points to users when a certain event happens (like watching a video or playing a game)

  • API call
POST /v1/users/{userId}/triggerEvent
  • Parameters:

    • token (string) token string that identifies the event (KWS will provide you with this).
    • points (number|optional) if omitted, the default amount of points will be given.
    • description (string|optional) Message the will be sent to the user in a notification. It can contain HTML (This message can contain the word {{POINTS}} that will be replaced by the corresponding amount of points).