Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
kayaelle Merge pull request #61 from kayaelle/master
Chaging redirect url to new repo location
Latest commit 684b888 Nov 18, 2014
Type Name Latest commit message Commit time
Failed to load latest commit information.


Directory for searching community badge classes.

Quick Start

npm install
npm run gulp                             #runs jshint, mocha, and then starts a watch process
DATABASE_URL=... npm run-script migrate #creates the database tables needed for directory
npm start                                #starts the actual search process

node_modules/.bin/gulp test              #run tests
node_modules/.bin/gulp integrationTest   #run integration tests (starts the api and makes calls against it)
node_modules/.bin/gulp lint              #run linter
node_modules/.bin/gulp watch             #watch

Badge Class Listing Format

Environment Variables

Project Structure

API Explorer


Curl'ing the API

Trying the examples

Invalid Badges

## Badge Class Listing Format

Currently, to have your badge classes indexed in the directory, you must expose an endpoint that lists the badges you want to have indexed. By endpoint, this just means a URL which when accessed returns a JSON message. The message is very simple and this is a valid example:

  "badgelist": [{
    "location": ""
  }, {
    "location": ""

There is a root key called "badgelist", which contains an array of badge class locations. These are objects with a single key of "location", pointing to the url where the badge class is hosted. When the directory retrieves a badge listing it collects up all of the locations and follows them to their badge class definitions.

For instance, let's say you are a badge issuer called badgetastic and your website is To participate in the directory, you would be expected to expose an endpoint somewhere (on your site or otherwise) that lists all of the badges you want indexed from badgetastic. The url is up to you, but assuming you host it on your site and expose the endpoint at - hitting that url we would expect to see a listing of badge locations as specified in the earlier code snippet. Each of these locations would be expected to lead to a valid badge class. For instance:

  "badgelist": [{
    "location": ""

Would be expected to have a valid badge class listing at
  "name": "Badge 1!",
  "description": "You speak computers and you can use them too.",
  "image": "",
  "criteria": "",
  "issuer": "",
  "tags": [

As well as inspecting the badge class itself, the directory will try and retrieve the issuer. If the issuer is in a valid Issuer Organization format, it will be parsed and the issuer name will be searchable in the directory.

Registering for the directory index

For simplicity, there is a form you can use to register with the directory at Behind the scenes, it hits the directory registration endpoint.

The register endpoint is described in the API section.

## Environment Variables

Mostly don't need environment variables at the moment, but if you don't want to use the dummy badge store located in the project itself, you can set the BADGE_STORE environment variable. It should

BADGE_STORE                             #full path to a JSON file of newline separated JSON objects
DATABASE_URL                            #URL to mysql - format is mysql://user:pass@host/database
ES_HOST                                 #(optional) URL to elasticsearch. Defaults to http://localhost:9200
INDEX_INTERVAL                          #(optional) Interval for indexing issuers in milliseconds. Defaults to 60 seconds.
EMAIL_SERVICE                           #Uses nodemailer internally, so requires one of the node nodemailer service names (example: 'SendGrid')
EMAIL_USER                              #Email service user
EMAIL_PASS                              #Email service password

If you are trying to load the example store for Discovery you'll need the following

URL                                     #The url (protocol, host, port) where your app lives
## Project Structure
/app.js - Starts the cluster
/config.json - Contains environment variables for local use (.gitignore'd, see config.json.example for a sample)
/gulpfile.js - Build tasks and tests
/developers - Contains the api-explorer, the swagger driven ui for interacting with the api directly
/examples - Example code for hitting the directory from the browser, and from the server
/lib - All of the main project code
  /api - API endpoint code
  /engine - 'engines' for indexing with either elasticsearch or lunr (elasticsearch by default, lunr isn't persistent or stable)
  /indexer - Worker script that indexes the available endpoints using the 'issuer' table
  /swagger - Swagger setup for the api-explorer
  /test - Short-term code for parsing the discovery badges
  /validator - Contains validation code for badge classes
/migrations - Contains all of the migrations for the project. Managed using 'db-migrate'
/test - Contains all the test (spec) files, written using mocha. Run using gulp (see "Quick Start")
## API Explorer

For an interactive experience with the api, go to /developers/api-explorer. This will load up a swagger powered interface that can directly invoke the api.

## API

All endpoints allow for a limit and page field to modify the number of results returned, and paginate the results.

  limit: int,
  page: int


Returns all badges by a search criteria. Currently allowed to have no criteria, but that may be changed since what is a search without any criteria?




  "data": [array of badges]


Returns all recently indexed badges. Does not accept any params.


  "data": [array of badges]


Returns a specific badge class, based on the location url (encoded).




  "data": {
    "location": ""
    ... badge class attributes ...


Returns all tags in the directory, sorted by most popular. This endpoint is not paginated, but does accept a 'limit' query.




  "data": [{
    "technology": 167
  }, {
    "conventional": 109
  }, {
    "organizer": 108
  }, {
    "doer": 91


Registers an endpoint for participation in the directory. Registering means that you have an endpoint in the valid badgelist format (go here to see the badgelist specified). The registration involves some required and optional fields. The fields are:

  • endpoint: Required field in a URL format. Specifies where the badgelist is being hosted.
  • name: Required field. Specifies your name.
  • website: Required field in a URL format. Specifies your website.
  • email: Required field for contact
  • description: Optional field to describe who you are and what your purpose for using the directory is
  • organization: Optional field for a possible organization name

POST Request

  "endpoint": ""
  "name": "Badgelister",
  "website": "",
  "email": ""
  "description": "We are devoted to listing badge classes",
  "organization": ""


  "data": { "success": true }

If there is a failed validation

  "status": "validation failed",
  "errors": {
    "email": {
      "code": "MISSING",
      "field": "email",
      "message": "Field is required"
## curl'ing the api
curl http://localhost:9000/recent

#get by searching all
curl http://localhost:9000/search?q=better

#get by searching tags
curl http://localhost:9000/search?tags=skill

#get by searching all w/ tags filter
curl http://localhost:9000/search?tags=skill,doer&q=better

#get by badge location
curl http://localhost:9000/http%3A%2F%2Flocalhost%3A9000%2Ftemp%2Fdiscovery%2Flisting%2F837

#get all tags, by popularity
curl http://localhost:9000/tags
## Trying the examples

There is an examples folder with a version of the service being proxied for a web client and a simple usecase of a server-side directory client.

To setup:

cd examples
npm install
npm run-script browserify

To run the client (from the examples folder):

npm run-script client
npm run-script server
#login to http://localhost:3000/example.html

To run the server example (from the examples folder):

npm run-script server
node server/example
## Invalid badges

This is not part of the standard API, but if you are hosting the directory and want to get a list of invalid badges, this is how you would hit your elastic search instance.

#get all invalid badges
curl -X POST -H "Content-Type: application/json" -d '{"query":{"bool":{"must":[{"term":{"_directory._valid": false}}]}}}' localhost:9200/badge_classes/badge_class/_search?pretty=1&from=0&size=100&sort=_timestamp

Approach so far + future

This API is a prototype to both integrate with the initial version of openbadges-discovery (, and also to serve a starting point for an actual badge directory API for the general badge community/ecosystem.

There are lots of questions surrounding how a directory would best work, and what it would be implemented on.

In terms of crawling and indexing badges: - badge indexing

In terms of extending badges (and what impact that may have on searching and retrieving): - badge class extensions - location info for badges/badge classes


MPL 2.0

You can’t perform that action at this time.