Submitting Applications

SueSmith edited this page Sep 28, 2014 · 16 revisions

In this guide we will work through the process of submitting an earner application for a badge with BadgeKit API. The example code will build on the code we used in Retrieving Badges, where we listed all available badges in a simple node.js app, letting users click through to a more detailed page on each individual badge. In that guide, we added a button linking to an apply page for each badge - you can use that as the basis for what we do here.

You do not have to use an assessment process with your BadgeKit implementation, but it is supported if you do need it. For an explanation of how assessment works in BadgeKit, see Assessment with BadgeKit. The repo docs also include an overview of the endpoints for assessment.

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

POST /systems/:slug/badges/:slug/applications
POST /systems/:slug/issuers/:slug/badges/:slug/applications
POST /systems/:slug/issuers/:slug/programs/:slug/badges/:slug/applications

See the API docs for more detail on the endpoints.

Expected Post Data Example

{ 
	"learner": "earneremail@example.com", 
	"evidence": [
		{ 
			"reflection": "text evidence"
		}, 
		{ 
			"mediaType": "image", 
			"reflection": "image description", 
			"url": "http://example.com/image.png"
		}, 
		{
			"mediaType": "link",
			"url": "http://example.com/evidence.html"
		}
	]
}

Parameters

All you need to submit an application is the earner email address (typically you will also want to include evidence). BadgeKit will retrieve the badge data from the endpoint path you request - here are the data items you can pass:

NAME VALUE
learner required - applicant email address
evidence optional - array (each item can include reflection, mediaType and url)
assignedTo optional - reviewer to assess application
assignedExpiration optional - expiry date

Authentication

Post data should be signed using your BadgeKit API secret and a JWT token in the Authorization header. See the Authorization doc for more.

Example Response

The API returns the status and application objects when an application is successfully submitted:

{
    "status": "created",
    "application": 
    {
        "id": 1,
        "slug": "abcdef123456",
        "learner": "earner@example.com",
        "created": "2014-05-06T12:24:45.000Z",
        "assignedTo": null,
        "assignedExpiration": null,
        "badge": 
        {
            "id": 1,
            "slug": "great-badge",
            "name": "Great Badge",
            "strapline": "General greatness.",
            "earnerDescription": "This badge shows how great you are.",
            "consumerDescription": "Earners of this badge are great.",
            "issuerUrl": "issuersite.com",
            "rubricUrl": "",
            "timeValue": 0,
            "timeUnits": "minutes",
            "limit": 0,
            "unique": 0,
            "created": "2014-05-05T14:17:46.000Z",
            "imageUrl": "http://issuersite.com/images/badge/1",
            "type": "",
            "archived": false,
            "system": 
            {
                "id": 1,
                "slug": "badgekit",
                "url": "systemsite.com",
                "name": "Excellent System",
                "email": null,
                "imageUrl": null
            },

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

                {
                    "id": 2,
                    "description": "Demonstrates greatness.",
                    "required": 1,
                    "note": ""
                }
            ],

            "categories": 
            [

            ]
        },

        "processed": null,
        "evidence": 
        [
            {
                "url": null,
                "mediaType": null,
                "reflection": "I did great stuff."
            }
        ]
    }
}

For a more detailed overview, read on.

Badge Applications

When an earner applies for a badge, depending on the badge, they may be required to include evidence supporting their application - this will typically relate to the criteria for the badge. You will also need the earner email address which will be associated with the badge if they are awarded it. If you're using the BadgeKit Web app in conjunction with the API, you will be able to view pending badge applications in there, accessing evidence submitted by applicants and submitting application reviews, which can include feedback to send to the earner.

The simple example we work through here will present the potential earner with a Web form including a text-field for their email address and a text-area in which they can include a summary of their application evidence. We will forward the earner application to the API, writing out a status update to the earner indicating whether or not their application has been submitted. When successfully submitted, the application will appear in the BadgeKit API database applications table, with an associated record in the evidence table.

When an application is submitted, the API will automatically add a foreign key to the database entry indicating the system ID for the badge the earner has applied for. If you are using the BadgeKit Web app, this will mean that the pending application will be visible to any users with permissions to review applications for that system. You can optionally also use the issuer and program admin levels to control this visibility.

Capturing Earner Application Input

Let's start using the apply page we indicated at the end of the guide to Retrieving Badges. We will again use a node.js example to demonstrate accessing the API endpoints and processing the returned data. The example code uses the following node resources: express, http, jws, crypto and qs. If necessary you can install these as follows:

npm install express
npm install http
npm install jws
npm install crypto
npm install qs
npm install body-parser

Then you can require them in your app:

//express
var express = require("express");
var app = express();
//http
var http = require("http");
//jws
var jws = require('jws');
//crypto
var crypto = require("crypto");
//qs
var qs = require("qs");
//body parser
var bodyParser = require('body-parser');
app.use(bodyParser.json());

We will create and handle the apply page as follows:

//APPLY PAGE
app.get('/apply', function(req, res) {
//application form
});

Remember that we included the following link in the badge detail page in last guide:

outputHTML+="<a href='apply?slug="+badgeData.slug+"'>Apply</a>";

We pass the badge slug for demonstration, for example:

apply?slug=your-badge-slug

Let's extend this a little by also passing the badge name:

apply?slug=your-badge-slug&name=Your%20Badge%20Name

To achieve this using the code we created for the apply link, you could build the parameters into the URL as follows (extending the example we used in the Retrieving Badges guide):

outputHTML+="<a href='apply?slug="+badgeData.slug+"&name="+badgeData.name+"'>Apply</a>";

Now in the function for the apply page, we can retrieve these as follows:

app.get('/apply', function(req, res) {
	var slug=req.param("slug");
	var badgeName=req.param("name");

//...
});

Application Form

For simplicity, we will write the HTML markup for our application form out at once - of course your own apps may involve more complexity. Inside the apply section, after retrieving the badge slug and name:

res.send("<html>"+
	"<head>"+
	"<title>Apply for "+badgeName+"</title>"+
	"<style type='text/css'>"+
	"//add some css"+
	"</style>"+
	"</head>"+
	"<body>"+
	"<h1>Apply for "+badgeName+"</h1>"+
	"<p>Include evidence for your application and your email address below:</p>"+
	"<form action='/sendApp' method='post'>"+
	"<input type='hidden' name='slug' value='"+slug+"'/>"+
	"Evidence:<br/><textarea rows='5' cols='50' name='evidence' required></textarea><br/>"+
	"Email:<br/><input type='email' name='email' required/><br/>"+
	"<input type='submit' value='Apply'/>"+
	"</form>"+
	"</body>"+
	"</html>"
);

We include the badge name visibly within the page (in the title and h1 elements) so that the earner knows they are applying for the correct badge. The form also includes a hidden field with the badge slug in it, so that we can access it when submitting the application to the API. It also includes a text-area for evidence and a text-field for the earner email address. We will use the input field names when we build the data to send to the API. We submit the form to a page named sendApp, posting the form data there - we will communicate with BadgeKit API in that page.

In your own site you may wish to include more supporting information about the badge in the application page. You can retrieve this information using the techniques we outlined in the Retrieving Badges guide, displaying whatever parts of the badge data you want earners to see when they submit an application. You may also wish to capture more detailed information and to carry out validation on the submitted data.

This is what our simple application form looks like with a little CSS added:

Application Form

Sending the Application

Now we can forward the earner application to the API in the sendApp page we listed as action for the form. We can include a section in our node.js app as follows:

//submit application
app.post('/sendApp', function(req, res) {
//submit form
});

In this section we will be able to retrieve whatever the user entered in the form. Inside the function, start by defining the application endpoint path:

var applicationPath = "/systems/badgekit/badges/"+req.body.slug+"/applications";

We retrieve the slug from the hidden form field value we included. This path applies where the badge is simply part of a system named badgekit - if you are using the issuer and/ or program admin levels for your badge, the endpoint is as follows:

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

See the API docs for more detail on the endpoints.

Now we need to build the earner application data into a JSON string, which we will sign and post to the API. The following structure packages the application data from the form into a string:

var appData = qs.stringify({
	learner: req.body.email, 
	evidence: [{ reflection: req.body.evidence }]
});

The application includes the the earner email (learner) and the evidence in an array (in this case a single item, with reflection as the field name). We will demonstrate additional evidence types below.

Authenticating the Data

We need to sign the application data using a slightly more complex technique than the one we use to retrieve badge data. Since we are posting information, we need to hash our post data before sending it. The following code demonstrates:

var claimData = {
	header: {typ: 'JWT', alg: 'HS256'},
	payload: {
		key: 'master',
		exp: Date.now() + (1000 * 60),
		method: 'POST',
		path: applicationPath,
		body: {
		      alg: "SHA256",
		      hash: crypto.createHash('SHA256').update(appData).digest('hex')
		    }
		},
	secret: 'yoursecret'
};

We use the path we defined and sign the JSON data string for the earner application, including it in the body object. You will of course need to alter the secret value to reflect your API secret. See also the Authorization document.

Now we can sign the claim data and package it for a post request:

var requestOptions = {
	host : 'yourapilocation.com', 
	path : applicationPath, 
	method : 'POST', 
	headers: { 'Authorization': 'JWT token="' + jws.sign(claimData) + '"',
		'Content-Type': 'application/x-www-form-urlencoded',
		'Content-Length': Buffer.byteLength(appData)
	}
};

You should include the location of your BadgeKit API as host. The method and path must be the same as what you included in the claim data or authentication will fail. We include the signed claim data in a JWT token in the Authorization header. We also use the application data to calculate the length.

Post the Data

Let's go ahead and post the application. We can create a request and pass the options we just prepared:

var postRequest = http.request(requestOptions, function(appResponse) { 
//respond
});

Inside this function we can handle any returned data and respond to the earner - hopefully telling them their application has been submitted. First we will prepare an array for storing the response from the server and set encoding:

var response = [];
appResponse.setEncoding('utf8');

In case the data arrives in chunks, we will push to the array each time we receive any:

appResponse.on('data', function (responseData) {					
	console.log('Response: ' + responseData);
	response.push(responseData);
});

We write each chunk to the console and push to the array. After this data function, we will listen for the end of the response data:

appResponse.on('end', function(){
//data end
});

In this function, we will join the array elements and parse them as JSON. This is an example of what the data structure will be if the application is successfully submitted:

{
	"status": "created",
	"application": 
	{
		"id": 21,
		"slug": "9cff7469124e91dc9921233605ed1058",
		"learner": "web@maker.com",
		"created": "2014-05-06T12:24:45.000Z",
		"assignedTo": null,
		"assignedExpiration": null,
		"badge": 
		{
			"id": 61,
			"slug": "mozilla-webmaker-basic-digital-mentor",
			"name": "Mozilla Webmaker Basic Digital Mentor",
			"strapline": "A commitment to exploring, encouraging and shepherding the development of digital expertise in the Mozilla Webmaker community and beyond.",
			"earnerDescription": "This badge acknowledges your commitment to exploring, encouraging, and shepherding community members inthe development of digital expertise in the Webmaker community. You earn this badge by working with the Mozilla Webmaker Team during 2014.",
			"consumerDescription": "Webmaking is an essential component to the sustainability of the worldwide web. This badge represents a personal commitment to exploring, encouraging, and shepherding community members in the development of digital expertise in the Mozilla Webmaker community. It involves any of the following activities: creating a teaching resource; hosting a webmaker event; or making and sharing through the Teach the Web online community. This badge is issued by the Mozilla Webmaker Team during 2014.",
			"issuerUrl": "www.webmaker.org",
			"rubricUrl": "",
			"timeValue": 0,
			"timeUnits": "minutes",
			"limit": 0,
			"unique": 0,
			"created": "2014-05-05T14:17:46.000Z",
			"imageUrl": "http://issuersite.com/images/badge/231",
			"type": "",
			"archived": false,
			"system": 
			{
				"id": 1,
				"slug": "badgekit",
				"url": "http://localhost:3000",
				"name": "Excellent System",
				"email": null,
				"imageUrl": null
			},

			"criteriaUrl": "http://issuersite.com/system/badgekit/badge/mozilla-webmaker-basic-digital-mentor/criteria",
			"criteria": 
			[
				{
					"id": 191,
					"description": "This badge demonstrates the earner has met Mozilla's stringent requirements for Basic Digital Mentor. This badge represents commitment to exploring, encouraging, and shepherding community members in developing digital expertise. It acknowledges the combined community building aspects of teaching and learning. Webmaker Mentors are an essential aspect to Mozilla's mission of making the web.",
					"required": 1,
					"note": ""
				},

				{
					"id": 201,
					"description": "The Basic Digital Mentor has taken one of our training courses and effectively completed one of the following requirements. Create a teaching resource. Create a hackable teaching kit using one of our handy templates. Submit your kit, activity, teaching guide or other teaching resource to help others teach the web or digital literacy to webmaker.org. Host a Webmaker event. Organize a hack jam, learning party or classroom event. Then document and share outcomes with the community. Our handy event guides make it easy. Make and share through the Teach the Web online community. Connect and learn other mentors around the world through remixing, making and discussion.",
					"required": 1,
					"note": ""
				},

				{
					"id": 211,
					"description": "This badge is issued by the Mozilla Webmaker Team during 2014. Mozilla Webmaker helps people teach digital and web literacy, learn new coding skills and make amazing things using digital tools.",
					"required": 1,
					"note": ""
				}
			],

			"categories": 
			[
				
			]
		},

		"processed": null,
		"evidence": 
		[
			{
				"url": null,
				"mediaType": null,
				"reflection": "I mentored lots of people in making web stuff."
			}
		]
	}
}

As you can see, the response includes lots of the badge information as well as the data representing the new earner application. You can choose to process this data in a way that suits your site, but we will simply check the status value to make sure the application has been created, writing out a response to the earner:

var appStatus=JSON.parse(response.join('')).status; 
if(appStatus==="created"){
	res.send("<html>"+
		"<head>"+
		"<title>Application Successful</title>"+
		"<style type='text/css'>"+
		"//add some css"+
		"</style>"+
		"</head>"+
		"<body>"+
		"<h1>Application Successful</h1>"+
		"<p>Thanks for your application! We'll be in touch when it's processed.</p>"+
		"</body>"+
		"</html>"
	);
}
else {
	res.send("Whoops! Something went wrong with your application.");
}

Here is the result with a little CSS added:

Application Successful

Finally, let's complete the sendApp page by handling errors and writing the application data via the request, at which point our data and end functions should fire. After the http.request function:

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

//write the application data
postRequest.write(appData);
postRequest.end();

At this point you should be able to run your app and submit an application. You should see the response data written to your console. You may also wish to check your API database - submitted applications will be represented by new entries in the applications and evidence tables. Each application will include the badge ID, the earner email and the system ID (as well as issuer and program IDs if you are using them). BadgeKit will generate an ID and slug for each application, with each entry in the evidence table listing the ID for the application it relates to. The reflection field in the evidence table will include whatever the earner entered into the form text-area.

Additional Evidence

You can submit multiple items of evidence along with an application. Each item of evidence may be a link, an image or a piece of text as in the above example. If you want your earners to be able to submit images, your own site can include an upload facility, then you can include the URL for the uploaded image in your API post.

The following extended excerpt from the node example above shows some additional form fields:

<form action='/sendApp' method='post' enctype='multipart/form-data'>
<input type='hidden' name='slug' value='"+slug+"'/>
Evidence:<br/><textarea rows='5' cols='50' name='evidence' required></textarea><br/>
Email:<br/><input type='email' name='email' required/><br/>
Image:<br/><input type='file' accept='image/*' name='pic' required/><br/>
Image description:<br/><textarea rows='5' cols='50' name='desc' required></textarea><br/>
Link:<br/><input type='url' name='link' required/><br/>
<input type='submit' value='Apply'/>
</form>

Here is the form in the page:

Application Form Extended

Then in your post function, you can read the uploaded file using a method of your choice. If you're using Heroku you can upload files to AWS. The following shows a simplified approach using fs and a middleware resource of your choice to handle multipart form data:

fs.readFile(req.files.pic.path, function (err, data) {
	var fileName = req.files.pic.name;
	var imagePath = __dirname+"/uploads/"+fileName;
	fs.writeFile(imagePath, data, function (err) {
		if(err)
    		res.send("Whoops!");
		else{
			//get image address
			var imgLink="http://yoursite.com"+imagePath;//amend to suit your site
			fs.unlink(req.files.pic.path);//delete temp file

			var applicationPath = "/systems/badgekit/badges/"+req.body.slug+"/applications";
			//build data to post
			var appData = qs.stringify({
				badge: req.body.slug, 
				learner: req.body.email, 
				evidence: [
					{ 
						reflection: req.body.evidence 
					}, 
					{ 
						mediaType: "image", 
						reflection: req.body.desc, 
						url: imgLink
					}, 
					{
						mediaType: "link",
						url: req.body.link
					}]
				});
				//build claim data, request options and call http.request...
		}
	});
});

How you handle uploading files will depend on your own site - the points to note in the above code relate to the structure of the appData JSON. Before we simply included a single item in the evidence array - this time we include three, one for a text string, one for the image we let the earner upload and one for a link. The image item includes the URL and a text string to accompany it. The mediaType field indicates the type in each case.

Reviewing Applications

If you are using the BadgeKit Web app, any users with permissions for the system, issuer or program your new applications relate to will be able to see them in the Applications > Pending section:

Pending Applications

When the application reviewer browses the application to assess it, they can see the submitted evidence:

Submitted Application

Multiple evidence items can be listed for each application:

Application Evidence List

The pending applications will be listed for each badge in BadgeKit until they are processed:

Application List

If you are not using the BadgeKit Web app, you can retrieve applications from the API using the following endpoints:

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

You can then submit application reviews using the following endpoints:

/systems/system-slug/badges/badge-slug/applications/application-id/reviews
/systems/system-slug/issuers/issuer-slug/badges/badge-slug/applications/application-id/reviews
/systems/system-slug/issuers/issuer-slug/programs/program-slug/badges/badge-slug/applications/application-id/reviews

Application Process

Note that if a reviewer approves a badge application, this does not meant that the badge is issued to the earner straight away. The process is as follows:

  • assessor submits application review
  • via BadgeKit app or issuer's own badge admin
  • issuer site receives notification via webhook*
  • issuer communicates with earner
  • providing feedback and offering badge if application was successful
  • earner accepts (or not) badge via issuer site
  • issuer site communicates with API to issue badge
  • issuer site receives notification of badge issue via webhook
  • issuer site can again communicate with earner
  • e.g. offering to push new badge to backpack

*See Application Review Webhooks for an overview of receiving the webhook data when an application review is submitted to BadgeKit.

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.