Retrieving Badges

SueSmith edited this page Sep 28, 2014 · 11 revisions

In this guide we will work through the steps required to retrieve badge data using BadgeKit API. If you have not yet installed the API, see the wiki homepage first.

In the below steps we will focus on the detail of retrieving badge data from the API - for a more general introduction to using the API, including an overview of supporting technologies, resources and concepts, see Using BadgeKit API. The repo docs also include an overview of the endpoints for retrieving badges.

The API guides use node.js examples to demonstrate the key processes you need to connect BadgeKit to your own earner-facing site. If you're using other languages/ platforms, you should be able to see how you can use BadgeKit to deliver your implementation.

Contents

Overview

Below is a detailed guide to using the API in the context of a node.js app - here's the short version!

Request Endpoints

GET /systems/:slug/badges
GET /systems/:slug/issuers/:slug/badges
GET /systems/:slug/issuers/:slug/programs/:slug/badges

See the API docs for more detail on the endpoints.

Authentication

Requests should be signed by including a JWT token in the Authorization header - see the Authorization document.

Example Response

{
    "badges": 
    [
        {
            "id": 1,
            "slug": "great-badge",
            "name": "Great Badge",
            "strapline": "This badge demonstrates greatness.",
            "earnerDescription": "Earning this badge means you are amazing.",
            "consumerDescription": "Earners of this badge are amazing.",
            "issuerUrl": "issuersite.com",
            "rubricUrl": "issuersite.com/rubric-great.html",
            "timeValue": 0,
            "timeUnits": "minutes",
            "limit": 0,
            "unique": 0,
            "created": "2014-04-25T10:10:53.000Z",
            "imageUrl": "http://issuersite.com/images/badge/1",
            "archived": false,
            "system": 
            {
                "id": 1,
                "slug": "badgekit",
                "url": "http://systemsite.com",
                "name": "Lovely System",
                "email": null,
                "imageUrl": null
            },

            "criteriaUrl": "http://issuersite.com/badge/great-badge/criteria",
            "criteria": 
            [
                {
                    "description": "Does great things. ",
                    "required": 1,
                    "note": ""
                },

                {
                    "description": "Is amazing.",
                    "required": 1,
                    "note": ""
                }
            ]
        },

        {
            "id": 2,
            "slug": "brilliant-badge",
            "name": "Brilliant Badge",
            "strapline": "This badge proves brilliance.",
            "earnerDescription": "If you earn this badge you are brilliant.",
            "consumerDescription": "Anyone who earned this badge is brilliant.",
            "issuerUrl": "issuersite.com",
            "rubricUrl": "issuersite.com/rubric-brilliant.html",
            "timeValue": 0,
            "timeUnits": "minutes",
            "limit": 0,
            "unique": 0,
            "created": "2014-04-25T10:22:42.000Z",
            "imageUrl": "http://issuersite.com/images/badge/2",
            "archived": false,
            "system": 
            {
                "id": 1,
                "slug": "badgekit",
                "url": "http://systemsite.com",
                "name": "Lovely System",
                "email": null,
                "imageUrl": null
            },

            "criteriaUrl": "http://issuersite.com/badge/brilliant-badge/criteria",
            "criteria": 
            [
                {
                    "description": "Does brilliant stuff.",
                    "required": 0,
                    "note": ""
                }
            ]
        },

        {
            "id": 3,
            "slug": "funny-badge",
            "name": "Funny Badge",
            "strapline": "Funny badge earners are funny.",
            "earnerDescription": "You deserve this badge if you are funny.",
            "consumerDescription": "Earners of this badge are funny.",
            "issuerUrl": "issuersite.com",
            "rubricUrl": "",
            "timeValue": 0,
            "timeUnits": "minutes",
            "limit": 0,
            "unique": 0,
            "created": "2014-04-25T14:04:48.000Z",
            "imageUrl": "http://issuersite.com/images/badge/3",
            "archived": false,
            "system": 
            {
                "id": 1,
                "slug": "badgekit",
                "url": "http://systemsite.com",
                "name": "Lovely System",
                "email": null,
                "imageUrl": null
            },

            "criteriaUrl": "http://issuersite.com/badge/funny-badge/criteria",
            "criteria": 
            [
                {
                    "description": "Is really funny",
                    "required": 1,
                    "note": ""
                },

                {
                    "description": "Tells funny jokes",
                    "required": 0,
                    "note": ""
                }
            ]
        }
    ]

For a more detailed overview, read on.

API Requests

BadgeKit API provides various endpoints for retrieving badge data. You can fetch the data for all badges in a System, Issuer or Program (if you are using these admin levels, otherwise you can simply fetch badges from your default System). You can also retrieve data for a particular badge and can filter the results to include (or exclude) archived badges.

As with all of the API calls, your requests must be authenticated.

Retrieving all badges within a System

You can retrieve all badges within a System using the following path:

"/systems/system-slug/badges"

See the API Docs for more details on the endpoint.

The system-slug should be the slug for your System, e.g. badgekit.

Every instance of BadgeKit API needs at least one entry in thesystems table in order to function - if you are not using the additional admin levels, your requests need only be preceded by the name of your default system.

The following code excerpt demonstrates how this might look in a node.js app, including authentication. In this example the System is named badgekit, the location of the BadgeKit API is yourapilocation.com and the API secret is yoursecret:

var jws = require('jws');

//...

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
		payload: {
			key: 'master',
			exp: Date.now() + (1000 * 60),
			method: 'GET',
			path: '/systems/badgekit/badges'
	},
	secret: 'yoursecret'
};

var requestOptions = {
	host : 'yourapilocation.com',
	path : '/systems/badgekit/badges', 
	method : 'GET', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"' }
};

Below we look at the response structure.

Retrieving badges within an Issuer

In BadgeKit admin, a System can include multiple Issuers. To retrieve the badges within an Issuer, the API provides the following endpoint:

"/systems/system-slug/issuers/issuer-slug/badges"

See the API Docs for more details on the endpoint.

Again, the system and issuer slug values should match what's in your BadgeKit API database.

Here is a corresponding node.js example:

var jws = require('jws');

//...

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
		payload: {
			key: 'master',
			exp: Date.now() + (1000 * 60),
			method: 'GET',
			path: '/systems/badgekit/issuers/newtown-library/badges'
	},
	secret: 'yoursecret'
};

var requestOptions = {
	host : 'yourapilocation.com',
	path : '/systems/badgekit/issuers/newtown-library/badges', 
	method : 'GET', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"' }
};

In this case the Issuer slug is newtown-library.

Retrieving badges within a Program

In BadgeKit admin, a System can have multiple Issuers and an Issuer can have multiple Programs. To retrieve the badges for a particular Program, the API provides the following endpoint:

"/systems/system-slug/issuers/issuer-slug/programs/program-slug/badges"

See the API Docs for more details on the endpoint.

The System, Issuer and Program slug values should match the entries in your BadgeKit API database.

The corresponding node.js example for this endpoint would be as follows:

var jws = require('jws');

//...

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
		payload: {
			key: 'master',
			exp: Date.now() + (1000 * 60),
			method: 'GET',
			path: '/systems/badgekit/issuers/newtown-library/programs/great-readers/badges'
	},
	secret: 'yoursecret'
};

var requestOptions = {
	host : 'yourapilocation.com',
	path : '/systems/badgekit/issuers/newtown-library/programs/great-readers/badges', 
	method : 'GET', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"' }
};

In this case the Program slug is great-readers.

Retrieving a particular badge

You can use BadgeKit API to retrieve the data for a specific badge using the following endpoint, which includes the badge slug:

"/systems/system-slug/badges/badge-slug"

See the API docs for more detail on the endpoint.

For a specific badge within an Issuer and/or Program, the path would be adjusted as follows:

"/systems/system-slug/issuers/issuer-slug/badges/badge-slug"
"/systems/system-slug/issuers/issuer-slug/programs/program-slug/badges/badge-slug"

In a node.js app, this request may appear as follows:

var jws = require('jws');

//...

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
		payload: {
			key: 'master',
			exp: Date.now() + (1000 * 60),
			method: 'GET',
			path: '/systems/badgekit/badges/fiction-reader'
	},
	secret: 'yoursecret'
};

var requestOptions = {
	host : 'yourapilocation.com',
	path : '/systems/badgekit/badges/fiction-reader', 
	method : 'GET', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"' }
};

In this case the badge slug is fiction-reader.

Filtering for archived badges

You can optionally supply an archived parameter to the badge retrieval requests (for endpoints returning multiple badges) - filtering to include/ not include archived badges:

//return only archived
"/systems/system-slug/badges?archived=true"

//return only unarchived
"/systems/system-slug/badges?archived=false"

//return all regardless of archived status
"/systems/system-slug/badges?archived=any"

Pagination

You can also supply optional pagination parameters to your request:

//count per page and page number to return
"/systems/system-slug/badges?page=2&count=5"

You can alter your path for Issuer and Program badges if necessary.

JSON Response

The method you use to make the request will depend on your own site. The following excerpt of a node app demonstrates:

var http = require("http");
//...

var apiRequest = http.request(requestOptions, function(apiResult) {
 
	apiResult.on('data', function(badgeData) {
		process.stdout.write(badgeData);
	});
 
});

This excerpt merely writes the data to standard output, but you can parse the JSON using a method of your choice, for example with JSON.parse(badgeData) in JavaScript.

BadgeKit API returns JSON data to your requests. The following example demonstrates a list of badges returned for a System:

{
	"badges": 
	[
		{
			"id": 31,
			"slug": "coffeelandia-assistant-store-manager",
			"name": "Coffeelandia Assistant Store Manager",
			"strapline": "Achieved level of Assistant Store Manager, can perform various store tasks. Leadership, financial expertise, and dynamic problem solving.",
			"earnerDescription": "Earning the Coffeelandia Assistant Store Manager represents significant commitment to the Coffelandia ethos. We believe in fair trade, fair work and fair play: our Assistant Managers represent those values and more. When you earn this badge, you earn a permanent and special place in our Coffelandia family.",
			"consumerDescription": "At Coffelandia, we believe in fair trade, fair work and fair play:  our Assistant Managers represent those high values and more. Earning the Coffeelandia  Assistant Store Manager represents an awesome commitment to the Coffelandia ethos and completion of our rigorous assistant manager training. These badge earners have not only  performed all of the roles and duties of all team members, they have also exhibited superior communication skills, dynamic customer service, and perhaps most importantly, they have repeatedly demonstrated a deep and abiding love for coffee and the people who drink it. We only wish that you could smell this badge because it would smell like Coffelandia love.",
			"issuerUrl": "www.coffeeland.ia",
			"rubricUrl": "",
			"timeValue": 0,
			"timeUnits": "minutes",
			"limit": 0,
			"unique": 0,
			"created": "2014-04-25T10:10:53.000Z",
			"imageUrl": "http://yourbadgekitappsite.com/images/badge/51",
			"archived": false,
			"system": 
			{
				"id": 1,
				"slug": "badgekit",
				"url": "http://yourbadgekitappsite.com",
				"name": "Lovely System",
				"email": null,
				"imageUrl": null
			},

			"criteriaUrl": "http://yourbadgekitappsite.com/badge/coffeelandia-assistant-store-manager/criteria",
			"criteria": 
			[
				{
					"description": "Performs all roles and duties of a Team Member. ",
					"required": 1,
					"note": ""
				},

				{
					"description": "Models, upholds, and communicates existing and new policies, practices, and standards. ",
					"required": 1,
					"note": ""
				},

				{
					"description": "Assists in development of and execution of local sales building and national marketing programs. ",
					"required": 1,
					"note": ""
				}
			]
		},

		{
			"id": 51,
			"slug": "civics-participation",
			"name": "Civics Participation",
			"strapline": "Successful completion of English instruction and other skills for state citizenship. Validation of work toward applying for US citizenship.",
			"earnerDescription": "As a State Civics Participation badge earner you indicate to the world your commitment to becoming a participating member of the state. This badge also contributes toward the completion of the requirements for US citizenship. ",
			"consumerDescription": "The State Civics Participation  demonstrates successful completion of English instruction and other required skills for state citizenship. It indicates completion of high school or  high school training equivalency. The Civic participation badge indicates the earner has plans to continue their education at a variety of levels at Technical College. This badge acts as validation of work toward applying for US citizenship.",
			"issuerUrl": "statecivics.com",
			"rubricUrl": "",
			"timeValue": 0,
			"timeUnits": "minutes",
			"limit": 0,
			"unique": 0,
			"created": "2014-04-25T10:22:42.000Z",
			"imageUrl": "http://yourbadgekitappsite.com/images/badge/21",
			"archived": false,
			"system": 
			{
				"id": 1,
				"slug": "badgekit",
				"url": "http://yourbadgekitappsite.com",
				"name": "Lovely System",
				"email": null,
				"imageUrl": null
			},

			"criteriaUrl": "http://yourbadgekitappsite.com/badge/civics-participation/criteria",
			"criteria": 
			[
				{
					"description": "    The State Civics Participation badge demonstrates the earner has met state requirements for English instruction and additional skills for state citizenship. The earner has taken classes in English instruction as well as additional training in job readiness. It indicates completion of high school or high school training equivalency. The Civic participation badge is one step in the pathway to continued education at a variety of levels at Technical College. This badge can act as validation of work completed toward applying for US citizenship.",
					"required": 0,
					"note": ""
				}
			]
		},

		{
			"id": 61,
			"slug": "dowell-and-co-group-leader",
			"name": "DoWell and Co Group Leader",
			"strapline": "The Group Leader badge acknowledges dynamic, effective leadership amongst peers in the realm of program facilitation.",
			"earnerDescription": "The Group Leader badge communicates that you are a leader amongst your peers. With it you demonstrate that you have effectively performed at least four of the following skills at DoWell and Co - communication, delegation, organization, responsibility & ownership, and passionate commitment.",
			"consumerDescription": "The DoWell & Co Group Leadership badge communicates important leadership values that we hold dear at DoWell & Co. Values that will serve an earner throughout their life. This badge represents breadth and depth of commitment to at least four of the five necessary leadership skills: communication, delegation,  organization, responsibility & ownership, and passionate commitment. Along with the other DoWell & Co badges, particularly Group Management and Time Management, the earning of this badge acknowledges exemplary achievement of the highest sort at DoWell & Co for groups of 7-12 members.",
			"issuerUrl": "dowellandco.co",
			"rubricUrl": "",
			"timeValue": 0,
			"timeUnits": "minutes",
			"limit": 0,
			"unique": 0,
			"created": "2014-04-25T14:04:48.000Z",
			"imageUrl": "http://yourbadgekitappsite.com/images/badge/91",
			"archived": false,
			"system": 
			{
				"id": 1,
				"slug": "badgekit",
				"url": "http://yourbadgekitappsite.com",
				"name": "Lovely System",
				"email": null,
				"imageUrl": null
			},

			"criteriaUrl": "http://yourbadgekitappsite.com/badge/dowell-and-co-group-leader/criteria",
			"criteria": 
			[
				{
					"description": "The Group Leader badge recognizes achievement in the realm of program facilitation. It acknowledges dynamic, effective interaction with peers in the completion of a group project. Group Leaders possess some form of at least four of the following five skills:\r\n\r\n-superior communication skills\r\n-effective delegation skills\r\n-advanced organization skills\r\n-personal responsibility & ownership skills\r\n-passionate commitment",
					"required": 1,
					"note": ""
				},

				{
					"description": "This badge illustrates expertise in reaching goals involving complex collaborative environments of groups ranging in size between 7 and 12 members.",
					"required": 0,
					"note": ""
				}
			]
		}
	]
}

If you're using the BadgeKit Web app to create and publish badges, some of the URLs in the data will point to the location you're hosting it at (or badgekit.org if you're using the Mozilla-hosted version).

For more about badge metadata, see the current assertion specification.

Example

Let's look at a more complete example of processing badges in a simple node.js app. Let's say our app's main script starts in the following standard way:

var express = require("express");
var logfmt = require("logfmt");
var app = express();
var http = require("http");
var jws = require('jws');

app.use(logfmt.requestLogger());

var port = Number(process.env.PORT || 5000);
app.listen(port, function() {
	console.log("Listening on " + port);
});

We will create a home page for the app in which we list all currently available published badges for a system. We will use the API call shown above to retrieve the list of badges, then we'll loop through it, writing the details of each one to the page, including the badge name, image and strapline.

We will also accompany each badge with a link to view more details in a second page. In that page we will retrieve the badge slug and query for the details of that particular badge, writing additional details to the page including the earner description and the badge criteria. You can alter the code to retrieve any of the other data items you see in the badge JSON.

Badge List

The following section will define what happens when the user visits the app home page:

//HOME PAGE
app.get('/', function(req, res) {

//query for badges using API endpoint

//show the list of badges in HTML

}

First inside this function, we can define the request data and sign it within our request options as we did in the above examples:

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
	payload: {
		key: 'master',
		exp: Date.now() + (1000 * 60),
		method: 'GET',
		path: '/systems/badgekit/badges?published=true'
	},
	secret: 'yoursecret'
};

var requestOptions = {
	host : 'yourapilocation.com',
	path : '/systems/badgekit/badges?published=true', 
	method : 'GET', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"' }
};

Now, still inside the app.get function for the home page, we can carry out the request:

var apiRequest = http.request(requestOptions, function(apiResult) {

	var response = [];
	apiResult.setEncoding('utf8');
	apiResult.on('data', function(badgeData) {
		response.push(badgeData);
	});
	apiResult.on('end', function(){
		//write the data out

	});

});

apiRequest.on('error', function(e) {
	console.error(e);
});
apiRequest.end();

Inside the data function we push the received data to an array in case it doesn't arrive in one chunk. Inside the end function we can process the final data and write parts of it to HTML:

//prepare the page outline - add some CSS!
var outputHTML="<html>"+
	"<head>"+
	"<title>BADGES</title>"+
	"<style type='text/css'>"+
	"//put some css here"+
	"</style>"+
	"</head>"+
	"<body>"+
	"<h1>Current Active Badges</h1>"+
	"<div class='badges'>";

//parse the returned badge data, badges are in a "badges" array
var badges=JSON.parse(response.join('')).badges; 
var b;
//loop through the array
for(b=0; b<badges.length; b++){
	//badge name in heading
	outputHTML+="<h2>"+badges[b].name+"</h2>";
	//badge image plus name in alt attribute
	outputHTML+="<img alt='"+badges[b].name+"' src='"+badges[b].imageUrl+"'/>";
	//strapline in paragraph
	outputHTML+="<p>"+badges[b].strapline+"</p>";
	//link to badge page including slug parameter
	outputHTML+="<a href='badge?slug="+badges[b].slug+"'>More</a>";
}
//finish page
outputHTML+="</div></body></html>";
//write HTML out
res.send(outputHTML);

For simplicity we create an HTML outline as a string variable - your own sites will likely use a more efficient method! Notice that we include a link to the page we will list the details for a particular badge in - we add the slug as a parameter to the URL, so we will be able to retrieve it when the user navigates to that page.

This is what the result looks like with a little CSS added:

Badge List

Badge Detail Page

Now let's create the page the badges link to. After the app.get('/' home page function, add another for the badge page:

//BADGE PAGE
app.get('/badge', function(req, res) {
//show the details for this badge
});

Inside the function, get the badge slug, which we passed as a parameter from the link in the badge listing above:

var slug=req.param("slug");
var badgePath="/systems/badgekit/badges/"+slug;

We build the path for the badge by adding the slug to the endpoint. This would require an adjustment if you're using the additional admin levels for Issuers and Programs.

Now we can use the same technique as above to create the claim data and request, with the path variable we just defined:

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
	payload: {
		key: 'master',
		exp: Date.now() + (1000 * 60),
		method: 'GET',
		path: badgePath
	},
	secret: 'yoursecret'
};

var requestOptions = {
	host : 'yourapilocation.com',
	path : badgePath, 
	method : 'GET', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"' }
};

Now we can make the request and include the same event functions as before (still inside the badge page section):

var apiRequest = http.request(requestOptions, function(apiResult) {
	var response = [];
	apiResult.setEncoding('utf8');
	apiResult.on('data', function(badgeData) {
		response.push(badgeData);
	});
	apiResult.on('end', function(){
		//process the data
	});
});

apiRequest.on('error', function(e) {
	console.error(e);
});
apiRequest.end();

Inside the on function, create the page outline, process the data and write the output as before:

var outputHTML="<html>"+
	"<head>"+
	"<title>BADGE</title>"+
	"<style type='text/css'>"+
	"//add some CSS"+
	"</style>"+
	"</head>"+
	"<body>";
	//the badge data is in "badge"
	var badgeData = JSON.parse(response.join('')).badge;
	//badge name in heading	
	outputHTML+="<h1>"+badgeData.name+"</h1>";
	outputHTML+="<div class='badge'>";
	outputHTML+="<img alt='"+badgeData.name+"' src='"+badgeData.imageUrl+"'/>";
	outputHTML+="<p>"+badgeData.strapline+"</p>";
	outputHTML+="<p class='desc'>"+badgeData.earnerDescription+"</p>";

	//loop through criteria - write to list
	var c;
	var criteria=badgeData.criteria;
	if(criteria.length>0) outputHTML+="<h2>Criteria:</h2><ul>";
	for(c=0; c<criteria.length; c++){
		outputHTML+="<li>"+criteria[c].description+"</li>";
	}
	if(criteria.length>0) outputHTML+="</ul>";
	
	//link to badge application page
	outputHTML+="<a href='apply?slug="+badgeData.slug+"'>Apply</a>";
	outputHTML+="</div></body></html>";
	res.send(outputHTML);

The endpoint for a single badge returns the badge data within the badge item in the JSON, rather than the badges array the list of badges was returned in. This time we also loop through the badge criteria, writing them out as a list. We include a link to an apply page, which you could use to facilitate earner applications - see Submitting Applications for an overview of how to do that based on the example we've built here.

Badge Page

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.