Overview
Install Guide
Dashboard User Guide
Integration Guide
Contribute
Overview
Install Guide
Dashboard User Guide
Integration Guide
Contribute
  • Overview
  • Install Guide

    • Overview
    • Quick Start
    • Distributions
    • Development Installation
    • Production Installation
    • Configuration
    • Installation Modes
  • Dashboard User Guide

    • Overview
    • Projects
    • Subjects
    • Skills
    • Self Reporting
    • Skills Catalog
    • Skill Groups
    • Description Editor
    • Quizzes and Surveys
    • Admin Groups
    • Badges
    • Learning Path
    • Progress and Ranking
    • Icons
    • Levels
    • Users
    • Metrics
    • Inception
    • Contact Admins
    • Settings
  • Integration Guide

    • Overview
    • Client App Integration
    • Authentication
    • Programmatic Endpoints
    • Legacy Frameworks
  • Open Source Contributions

    • Contribution Guidelines
    • Architecture
    • Development Environment
  • Release Notes

    • Overview
    • Dashboard and API Release Notes
    • Client Libraries Release Notes

Programmatic Endpoints

Client side libraries take care of reporting skills and visualizing display results, however there are times when you may want to call programmatic endpoints directly.

Some examples include:

  • You may not be able to use one of the supported frameworks to reports skills
  • You may need to report skill events from server side components

Please Note

If you are looking for endpoints to retrieve progress and ranking data, that is not supported by the SkillTree platform. In liu of those endpoints and in order to support rapid integration SkillTree has taken an innovative approach of supplying fully navigable Ranking and Visualization views. Please take a look at the Integration Guide Overview to learn more.

Public Endpoints (only 1 so far):

  • [Service URL]/api/projects/[Project Id]/skills/[Skill Id]
    • HTTP Methods: POST, PUT
    • Purpose: Report Skill Events
    • Detailed Description: Click Here

This endpoint requires authentication and a user id in order to perform its functions. Please select your installation type below for specific instructions:

Visit to learn about this mode: Password Auth Install

In Password Auth Installation, the OAuth2 protocol is utilized, you will need to:

  1. retrieve user specific temporary client token
    • using project's Client ID and Client Secret (found in the dashboard under Project -> Access -> 'Trusted Client Properties' ).
    • user-to-proxy-for is provided in the request (this is the user id).
    • result token encapsulates the user id so the service will know what user to perform this action for
  2. call the endpoint and set the user token on the request.

Here is a CURL based example: (please substitute your values of client-id, client-secret, dashboard-url and user-to-proxy-for):

curl client-id:client-secret@dashboard-url/oauth/token -d "grant_type=client_credentials&proxy_user=user-to-proxy-for"

and then (please substitute your values of access_token_from_first_call, dashboard-url):

curl -H "Authorization: Bearer access_token_from_first_call" http://dashboard-url/api/projects/FirstProject/level

Report Skill Event Endpoint

If the existing libraries do not suffice or you need to report skill events from your server components (e.g., batch, async, streaming, etc..), then you can [POST](https://en.wikipedia.org/wiki/POST_(HTTP) / PUT to the endpoint directly in order to report a single skill event:

[Service URL]/api/projects/[Project Id]/skills/[Skill Id]

where

  • Service URL: Fully qualified URL of the skills service/dashboard, if you are running it locally then something like http://localhost:8082
  • Project Id: Project id for the reported skill
  • Skill Id: For the reported skill

For example, to report a skill with id SkillA for a project with id ProjectA, for a locally hosted service, POST to the following URL:

http://localhost:8080/api/projects/ProjectA/skills/SkillA

The Report Skill Endpoint also accepts optional JSON payload parameters.

Visit to learn about this mode: Password Auth Install
ParameterExplanation
userId(optional) Report skill event on behalf of another user (must be an admin of the project).
timestamp(optional) Report skill event in the past (must be an admin of the project).
notifyIfSkillNotApplied(optional) If set to true, notify all client global event handlers even if the reported skill is not applied. Defaults to false.

Here is an example JSON payload for reporting a skill event for another user in the past:

{
  "userId":"valueForUserId",
  "timestamp":1581349194294,
  "notifyIfSkillNotApplied": false
}

Keep In Mind

Only a project admin is allowed to supply userId and timestamp.

Keep In Mind

Only a project admin is allowed to supply userId and timestamp.

Endpoint Result Object

Skill events are applied immediately and atomically based on the currently configured ruleset (via dashboard). The endpoint returns an object that depicts how this event affected the user's progress.

Event result object provides:

  • status - whether skill was applied or rejected
  • if skill was rejected, reason for that rejection
  • achievements completed by this event including
    • completion of a skill
    • leveling-up for a project or a subject
    • achievement of a badge or a gem

Here is an example of an event that (1) was successfully applied, (2) completed/achieved that skill, and (3) achieved level 2 for subject named Cool Subject

{
   "success":true,
   "projectId":"sampleProject",
   "skillId":"ImportantSkill",
   "name":"Important Skill",
   "pointsEarned": 15,
   "totalPointsEarned": 30,
   "totalPoints": 30,
   "numOccurrencesToCompletion": 2,
   "skillApplied":true,
   "explanation":"Skill event was applied",
   "completed":[{
      "type":"Subject",
      "level":2,
      "id":"CoolSubjectId",
      "name":"Cool Subject"
    }, {
      "type":"Skill",
      "level":null,
      "id":"ImportantSkill",
      "name":"This is a very important skill"
    }]
}

Here is a reference table for result fields and their meaning:

FieldTypeExplanation
successbooleantrue if there were no issues reporting the skill, false if there was a server side failure - this could happen if the service is down or you stumbled on a bug
projectIdstringthe projectId that the report skill belongs to
skillIdstringthe skillId of the report skill
namestringthe display name of the report skill
pointsEarnednumbernumber of points earned by this request
totalPointsEarned 🕓 Since skills-service:3.3numbertotal points earned by this user for this skill
totalPoints 🕓 Since skills-service:3.3numbertotal points defined by an administrator for this skill
numOccurrencesToCompletion 🕓 Since skills-service:3.3numbernumber of times skill needs to be performed to earn all its points
skillAppliedbooleantrue if this event contributed points to the skill; false if the event didn't contribute points - explanation field will tell you why (see examples below)
explanationstringhuman readable explanation about how this skill event was handled; this field will explain why an event wasn't able to contribute points (see examples below)
completedlistmetadata of a completed item if this event caused user to level-up, complete a skill or earn a badge/gem (just to mention a few)
completed.typestringtype of the completed item, will be one of these well-known values: Overall, Subject, Skill, Badge. Overall indicates that the user leveled-up for the entire project, Subject indicates that the user leveled-up for a specific subject, Skill indicates that this skill is fully accomplished, Badge indicates that a badge/gem was earned.
completed.levelintindicates which level the user achieved via this skill event; only applicable to Overall and Subject types
completed.idstringid of the completed item, in the case of Skill type this will be skill id, in the case of Subject type it will be subject id and so on...
completed.namestringhuman friendly name of the event and can be used to display to the end user

Here is an example where the skill event did not contribute any points because it's already fully accomplished:

{
   "success":true,
   "projectId":"sampleProject",
   "skillId":"ImportantSkill",
   "name":"Important Skill",
   "pointsEarned": 0,
   "totalPointsEarned": 200,
   "totalPoints": 200,
   "numOccurrencesToCompletion": 2,
   "skillApplied":false,
   "explanation":"This skill reached its maximum points",
   "completed":[]
}

Here is an example where the skill event did not contribute any points because it has unfulfilled dependencies:

{
   "success":true,
   "projectId":"sampleProject",
   "skillId":"ImportantSkill",
   "name":"Important Skill",
   "pointsEarned": 0,
   "totalPointsEarned": 0,
   "totalPoints": 200,
   "numOccurrencesToCompletion": 2,
   "skillApplied":false,
   "explanation":"Not all dependent skills have been achieved. Missing achievements for 1 out of 1. Waiting on completion of [FirstProject:skill1Skill].",
   "completed":[]
}

Below is an example where the skill contributed points but did not complete anything:

{
   "success":true,
   "projectId":"sampleProject",
   "skillId":"ImportantSkill",
   "name":"Important Skill",
   "pointsEarned": 15,
   "totalPointsEarned": 30,
   "totalPoints": 45,
   "numOccurrencesToCompletion": 3,
   "skillApplied":true,
   "explanation":"Skill event was applied",
   "completed":[]
}

Above skill has Occurrences to Completion > 1 and additional skill events must be reported to fulfill the required occurrences. Once all of the required occurrences are reported then the skill completion will appear in the completed field.

Tips

You can use this result object to implement a messaging center - to report messages of encouragement to your users as they complete skills, level-up and earn badges.

Java Examples

Visit to learn about this mode: Password Auth Install

Reporting skill event programmatically is two-fold:

  1. Retrieve token for a specific user id
    • utilize Client Id and Client Secret found under Trusted Client Properties on project's Access page
  2. Using the token report the event for a skill id
    • if the token retrieved in step 1 has Admin privileges then the skill can be reported for any user, otherwise only for the user represented by the token

Here is an example of retrieving a token for a given user and reporting one skill for that user:

public class ReportExample {

    public static void main(String[] args) throws Exception {
        // "Client Id" and "Client Secret" found under 
        // "Trusted Client Properties" on project's "Access" page
        ReportExample reportJavaExample = 
                new ReportExample(
                        "<PROJECT_ID>", 
                        "<SECRET>", 
                        "<PROTOCOL>", 
                        "<HOST>");
        String token = reportJavaExample.getToken("<USER_ID>");
        String res = reportJavaExample.reportSkill(token, "<SKILL_ID>");
        System.out.println(res);
    }


    private final String projectId;
    private final String secret;
    private final String protocol;
    private final String host;

    public ReportExample(String projectId, 
                         String secret, 
                         String protocol, 
                         String host) {
        this.projectId = projectId;
        this.secret = secret;
        this.protocol = protocol;
        this.host = host;
    }

    public String getToken(String userID) throws Exception {
        String authUrl = protocol + "://"+ projectId + 
                ":" + secret + "@" + host + "/oauth/token";

        List<NameValuePair> authParameters = new ArrayList<>();
        authParameters.add(
                new BasicNameValuePair("grant_type", "client_credentials"));
        authParameters.add(
                new BasicNameValuePair("proxy_user", userID));
        HttpPost authPost = new HttpPost(authUrl);
        authPost.setEntity(new UrlEncodedFormEntity(authParameters));

        String token = "";
        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(authPost)) {
            String tokenInfo = EntityUtils.toString(response.getEntity());
            JSONObject tokenJson = new JSONObject(tokenInfo);
            token = (String) tokenJson.get("access_token");
        }

        return token;
    }

    public String reportSkill(String token, String skillId) 
            throws Exception {
        String reportUrl = protocol + "://"+ 
                host + "/api/projects/" + projectId + "/skills/" + skillId;

        HttpPost post = new HttpPost(reportUrl);
        post.setHeader("Authorization", "Bearer " + token);

        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(post)) {
            return EntityUtils.toString(response.getEntity());
        }
    }
}

Here is an example of retrieving a token for a user with project admin privileges and then reporting a skill for a different user:

public class ReportForAnotherUserExample {

    public static void main(String[] args) throws Exception {
        // "Client Id" and "Client Secret" found under 
        // "Trusted Client Properties" on project's "Access" page
        ReportForAnotherUserExample reportJavaExample = 
                new ReportForAnotherUserExample(
                        "<PROJECT_ID>", 
                        "<SECRET>", 
                        "<PROTOCOL>", 
                        "<HOST>");
        // must be an admin of <project_id>
        String token = reportJavaExample.getToken("<USER_ID>");
        String res = reportJavaExample.reportSkillForAnother(
                token, 
                "<ANOTHER_USER_id>", 
                "<SKILL_ID>", 
                new Date());
        System.out.println(res);
    }
    
    private final String projectId;
    private final String secret;
    private final String protocol;
    private final String host;

    public ReportForAnotherUserExample(
            String projectId, String secret, 
            String protocol, String host) {
        this.projectId = projectId;
        this.secret = secret;
        this.protocol = protocol;
        this.host = host;
    }

    public String getToken(String userID) throws Exception {
        String authUrl = protocol + "://"+ 
                projectId + ":" + secret + "@" + host + "/oauth/token";

        // First setup token
        List<NameValuePair> authParameters = new ArrayList<>();
        authParameters.add(
                new BasicNameValuePair("grant_type", "client_credentials"));
        authParameters.add(
                new BasicNameValuePair("proxy_user", userID));
        HttpPost authPost = new HttpPost(authUrl);
        authPost.setEntity(new UrlEncodedFormEntity(authParameters));

        String token = "";
        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(authPost)) {
            String tokenInfo = EntityUtils.toString(response.getEntity());
            JSONObject tokenJson = new JSONObject(tokenInfo);
            token = (String) tokenJson.get("access_token");
        }

        return token;
    }

    public String reportSkillForAnother(String token, 
                                        String pointsForThisUser, 
                                        String skillId, 
                                        Date performedOn) throws Exception {
        String reportUrl = protocol + "://" + 
                host + "/api/projects/" + projectId + "/skills/" + skillId;

        HttpPost post = new HttpPost(reportUrl);
        post.setHeader("Authorization", "Bearer " + token);

        // Add request parameters
        String jsonString = "{\"userId\":\"" + 
                pointsForThisUser + "\", \"timestamp\":\"" + 
                performedOn.getTime() + "\"}";
        post.setEntity(
                new StringEntity(jsonString, ContentType.APPLICATION_JSON));

        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(post)) {
            return EntityUtils.toString(response.getEntity());
        }
    }
}

This example is using Apache HttpClient library so you will need to add it to your classpath. For example, in Maven it would look something like this:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>${version}</version>
</dependency>
Prev
Authentication
Next
Legacy Frameworks