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 App Config

This endpoint returns the configuration of an app based on the clientId passed as a query parameter.

  • API call
GET /v1/apps/config
  • Parameters:

    • oauthClientId (string) client ID of the application.
  • Response:

    • id (number) ID of the app.
    • name (string) Display name.
    • oauthClientId (string) Client ID; should be the same as the client ID passed as a query param.
    • oauthCallbackUrls (array) Array of approved values to accept as redirectUri. Only values in this array will be accepted when authenticating the user, and only these URLs should be redirected to after the user authenticates.
    • parentEmailRequired (boolean) Whether or not it’s required to collect the parent’s email address of the user regardless of their age. If false, parent email is only reuired for underage users.
    • areAnonAccountsEnabled (boolean) Whether or not anonymous accounts are enabled. If so, users can sign up without providing a date of birth.
    • languages (array) List of supported languages.
  • Response example

{
        "app": {
                "id": 1,
                "name": "Test App",
                "oauthClientId": "test-app",
                "oauthCallbackUrls": ["https://www.superawesome.com/redirect-uri"],
                "parentEmailRequired": true,
                "areAnonAccountsEnabled": false,
        },
        "languages": ["de", "en", "es", "fr", "it", "ja", "ko", "pt-br", "zh-tw"]
}

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"

Get Random names data

This endpoint gets the list of nouns and adjectives for random name generation

  • API call
GET /v1/apps/{appId}/randomNames
  • Response:

    • [language].words (object) object with nouns and adjectives for a given language
      • [language].words.nouns (array) array of object with the list of nouns for a given language
        • [language].words.nouns[i].value (array) noun
        • [language].words.nouns[i].gender (string) “m” for masculine, “f” for feminine and “n” for neutral
      • [language].words.adjectives (object) object with feminine, masculine and neutral adjectives
        • [language].words.adjectives.f (array) array of objects defining feminine adjectives
        • [language].words.adjectives.m (array) array of objects defining masculine adjectives
        • [language].words.adjectives.n (array) array of objects defining neutral adjectives
          • [language].words.adjectives.[gender][i].value (array) adjective
          • [language].words.adjectives.[gender][i].beforeNoun (boolean) boolean indicating whether the adjective should be added before the noun in a random name
  • Response example

{
        "en": {
                "nouns": [{
                        "value": "Dragon",
                        "gender": "n"
                }, {
                        "value": "Monster",
                        "gender": "n"
                }],
                "adjectives": {
                        "n": [{
                                "value": "Unbeatable",
                                "beforeNoun": true
                        }, {
                                "value": "Evil",
                                "beforeNoun": true
                        }]
                }
        },
        "es": {
                "nouns": [{
                        "value": "Dragón",
                        "gender": "m"
                }, {
                        "value": "Bestia",
                        "gender": "f"
                }],
                "adjectives": {
                        "f": {
                                "value": "Malvada",
                                "beforeNoun": false
                        },
                        "m": {
                                "value": "Malvado",
                                "beforeNoun": false
                        }
                }
        }
}

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

Create user

This endpoint creates a new child user.

  • API call
POST /v2/users
  • Parameters:

    • username (string|optional) login username. Required if child below threshold parental consent age. Must be at least 3 characters long, must start by a letter and can contain only alphanumeric, “-” or “_”
    • password (string) login password. Must be at least 5 characters long.
    • dateOfBirth (string|optional) Date of birth of the user in the format YYYY-MM-DD. It is normally required, but it might depend on the cluster setup.
    • parentEmail (string|optional) : Email address of the parent. Required only for children under threshold parental consent age.
    • email (string|optional) : Email address of the user. Required only if child above threshold parental consent age. Forbidden otherwise.
    • country (string|optional) : country of the user. It can be ommited if unknown.
  • Response:

    • id (number) id of the created user
  • Response example

"{id: 374382}"

Delete account

Delete a users account.

  • API call
POST /v1/users/deleteAccount
  • Parameters:

    • password (string)

Forgot Password

This endpoint allows you to initiate the forgot password flow for a user, triggering an email to be sent to either the child’s email address (if set) or their parent’s email address. The email contains a link which will take the user to a page where they can reset their password. If necessary, the link can be altered in the control panel.

  • API call
POST /v1/users/forgotPassword
  • Parameters:

    • username (string)
    • appName (string|optional) the client ID of the app this request was made from, if applicable (used for branding the email)

Reset Password

This endpoint allows you to use a token to reset a child’s password. The reset password token is generated by KWS and sent to the child (or their parent) via email when the forgot password flow is triggered. After the password is reset, a confirmation email will be sent to the child (or their parent). Please note that this endpoint is only necessary if you are implementing your own ‘forgot password’ flow.

  • API call
POST /v1/users/resetPassword
  • Parameters:

    • token (string)
    • newPassword (string)
    • appName (string|optional) the client ID of the app this request was made from, if applicable (used for branding the email)

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

Activate Application

Used for activating a user in the context of an application. A user cannot log in to or interact with an application until they’ve been activated within this application.

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

    • appName (string) client ID of the application.
    • username (string) Display name of the user within the application; this is unique across users and across applications.
    • permissions (array) Array of permissions to request; notification of these requests will be sent along with the activation notification email.
    • dateOfBirth (string) Date of birth of the child, if not already set. May be required, depending on the app’s settings.
    • parentEmail (string) Parent’s email address. May be required, depending on the app’s settings, or the newly added date of birth if set.

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)

Backend API

The API calls listed in this section are available for authenticated apps. In other words, the access token needed has to be obtained by the Client Credentials flow explained in the subsection. Thus, the necessary scope of the token is app.

Update random names list

This call allows you to update the list of words for random display name generation

  • API call:
PUT /v1/apps/{appId}/random-names
  • Parameters:

    • words (Object, required) object that has a sub-object for every language with nouns and adjectives. Each of these sub-objects has the language code as key, and then nouns and adjectives with the following format:

      • nouns (Array of objects, required): Each item of the array has the following fields:
        • value (String, required): the noun
        • gender (f|m|n, optional): gender of the noun (feminine, masculine or neutral). It can be ommitted if it does not apply, like in English.
      • adjectives (Object, required): this object can contain up to 3 fields whose keys would be “f” for feminine, “m” for masculine and “n” for neutral adjectives. Neutral can be used for the languages where it does not apply (like English). Each of these fields will contain an array of objects with the following format

        • value (String, required): the adjective
        • beforeNoun (boolean, required): whether the adjective should be added before the noun or not.

    Example:

{
    "en": {
      "nouns": [
        { "value": "Dragon" },
        { "value": "Monster" }
      ],
      "adjectives": {
        "n": [
          { "value": "Unbeatable", "beforeNoun": true },
          { "value": "Evil", "beforeNoun": true }
        ]
      }
    },
    "es": {
      "nouns": [
        { "value": "Dragón", "gender": "m" },
        { "value": "Bestia", "gender": "f" }
      ],
      "adjectives": {
        "f": { "value": "Malvada", "beforeNoun": false },
        "m": { "value": "Malvado", "beforeNoun": false }
      }
    }
}
  • Response: Empty

  • Examples of random names that would be generated:

    • English: UnbeatableDragon, EvilMonster, UnbeatableMonster, EvilDragon
    • Spanish: DragónMalvado, BestiaMalvada