Integration with other platforms part 2

With Open Badge Factory you can create and manage your badges in one place and issue them from other platforms, which are usually Learning Management Systems. There are 3 ways to get OBF integrated with other platforms. you can use some existing plugins, LTI (Learning Tools Interoperability) to connect with LTI compatible platforms or you can develop your own OBF plugin using  OBF RESTful API.


The Open Badge Factory team develops, maintains and supports OBF issuer and OBF displayer plugins for Moodle. Other plugins listed here are developed by learning service providers, partners, third party developers or by some open source projects. The plugins listed here are used by our customers and have been reported to work fine, but the OBF team is not responsible for their use and technical questions and development requests should be addressed to plugin developers. Notice also that plugins can be available at different service levels. We welcome all developers who would be interested in contributing to the development of our Moodle plugin or other coming open source projects.

Moodle plugin

LTI integration

Open Badge Factory LTI (1.1) Integration provides a link between an LTI supported LMS and Open Badge Factory. Our customers use LTI integration for example with Canvas LMS, Blackboard, Brightspace. LTI integration requires Pro subscription level. Please log in into your Open Badge Factory Pro account and go to Admin Tools > LTI for more information.


Mahara issuer plugin — github project

Mahara displayer plugin — github project


Moodle issuer plugin — github project

Moodle displayer plugin — github project

Totara (

WordPress (

Open Badge Factory LTI Integration provides a link between an LTI supported LMS and Open Badge Factory.

LTI integration is available at Pro subscription level.
Please log in and go to Admin Tools > LTI for more information.

Installation guides and instructions

Get our public RSA key

Decode your API key with our public key

in Perl:

my $key = Crypt::OpenSSL::RSA->new_public_key($pubkey);
 my $decrypted = $key->public_decrypt( decode_base64( $apikey ) );
 my $json = decode_json($decrypted); 

Formats and encodings

Unless otherwise noted, all input and output is JSON encoded. String encoding is always UTF-8.

Lists of objects are returned as Line Delimited JSON:

{"key1":"...","key2":"..." ... ,"keyX":"..."}\r\n
{"key1":"...","key2":"..." ... ,"keyX":"..."}\r\n
{"key1":"...","key2":"..." ... ,"keyX":"..."}\r\n
{"key1":"...","key2":"..." ... ,"keyX":"..."}\r\n

Badge Operations

Create new badge

POST /v1/badge/{client_id}

Input JSON object parameters:name (String)

Name of the badge. Required.description (String)

Description of the badge. Required.image (String)

Base64 encoded PNG image data.css (String)

Criteria page styles.criteria_html (String)

Criteria page HTML.email_subject (String)email_body (String)email_link_text (String)email_footer (String)

Email chunks for issuing messages.expires (Int)

Unix timestamp for optional badge expiration date.tags (Array)

Array of strings representing badge tags.draft (Boolean)

Badge status. Required.metadata (Object)

Custom badge metadata. Optionally you can define your platform-specific metadata and store it with the badge. This field can be used to store any valid JSON object. The data is used internally only and it won’t be present in issued badges.

Update new badge

PUT /v1/badge/{client_id}/{badge_id}

Same input parameters as create. Doesn’t affect already issued badges.

Delete new badge

After deletion a badge is no longer available for issuing. Doesn’t affect already issued badges.Delete all badges:

DELETE /v1/badge/{client_id}

Delete single badge:

DELETE /v1/badge/{client_id}/{badge_id}

Get new badge

Single badge by id:

GET /v1/badge/{client_id}/{badge_id}

All badges:

GET /v1/badge/{client_id}

Optional query parameters:

  • draft (0|1)Allows you to filter badges by status. If not present, all badges are returned.
  • category (String)Badges can belong in one or more categories. These are used for internal purposes only and are different from OBI badge tags. Multiple categories can be separated in query by pipe sign: ?category=cat1|cat2|cat3 Available categories: GET /v1/badge/{client_id}/_/categorylist
  • id (String)List of badge ids to fetch, separated by pipe sign.
  • query (String)Search badges by name or description.
  • meta:{key} (String)Filter badges by metadata. For example, given badge metadata field: {"foo":123, "bar":456, "baz":"quux"} Matching query: ?meta:foo=123&meta:baz=quux No match: ?meta:foo=124

Issue badge

When you issue a badge your recipients will get an email message containing an url where they can accept the badge and add it to their backback.

POST /v1/badge/{client_id}/{badge_id}

Input JSON object parameters:recipient (array)

List of recipient email addresses. Required.expires (int)

Unix timestamp for optional badge expiration.issued_on (int)

Unix timestamp, current time is used by default.email_subject (String)email_body (String)email_link_text (String)email_footer (String)

Email chunks for issuing message. Required, unless the message has been stored with the badge.badge_override (object)

Overrides badge data for this particular issuing event. Allowed keys:

  • name
  • description
  • criteria
  • tags

Values provided here will replace the content of the badge. In addition, key criteria_add can be used to append content to the original criteria text.log_entry (object)

A log entry object of unspecified format can be saved along the issuing event.api_consumer_id (String)

Parameter identifying this client.

Return code: 201 Created

Location header field contains url of this issuing event.

Badge revocation

After you revoke a badge, GET requests to it’s assertion url will return 410 Gone response. This tells displayers that the badge is no longer valid.

Badges are revoked with an issuing event id and one or more recipient email addresses. If a recipient has been issued the same badge multiple times, only the one identified by event id is revoked.

See Report section of this document for more information on issuing event operations.Revoke a badge:

DELETE /v1/event/{client_id}/{event_id}/?

DELETE /v1/event/{client_id}/{event_id}/?||

Return code: 204 No ContentGet revoked badges:

GET /v1/event/{client_id}/{event_id}/revoked

Sample output:

    "revoked": {
        "": 1434971021, // recipient email address and revocation timestamp
        "": 1434971020,

Return code: 200 OK

Issuer Operations

Update own data

PUT /v1/client/{client_id}

Input JSON object parameters:url (String)

Issuing organization’s web address. Required.description (String)

Description of the issuer. (String)

Canonical email address of the issuer. Required.image (String)

Base64 encoded image representing the issuer, a logo.

Get own data

GET /v1/client/{client_id}

Badge Applications

Get earnable badges

List all:

GET /v1/earnablebadge/{client_id}/

Query parameters:

  • client_alias (String)Filter by client alias id
  • badge_id (String)Find earnable badges by badge id
  • appoval_method (review|instant|secret|peer)Find earnable badges by approval method
  • visible (1|0)Filter by visibility status

Single earnable badge by id:

GET /v1/earnablebadge/{client_id}/{earnable_id}

Get applications

List all applications to a badge:

GET /v1/earnablebadge/{client_id}/{earnable_id}/application

Query parameters:

  • status (approved|pending|rejected)Filter by application status

Single application by id (contains application form data):

GET /v1/earnablebadge/{client_id}/{earnable_id}/application/{application_id}

Process applications

Approve or reject:

PUT /v1/earnablebadge/{client_id}/{earnable_id}/application/{application_id}

Input JSON object parameters:result (approve|reject)

Result of assessmentreviewer (String)

Reviewer’s identification stringexpires (int)issued_on (int)email_subject (String)email_body (String)email_link_text (String)email_footer (String)log_entry (object)api_consumer_id (String)

Approval parameters, see badge issuing section for details.

If application is rejected, you can optionally send rejection message using email_subject and email_body parameters. Other issuing parameters are not used in this case.


Get issuing events

Single event by id:

GET /v1/event/{client_id}/{event_id}

Search for events:

GET /v1/event/{client_id}

Query parameters:

  • api_consumer_id (String)Filter by issuer plugin id.
  • badge_id (String)Filter by badge id.
  • email (String)Filter by recipient email address.
  • begin (Int)
  • end (Int)Filter by issuing event date range. Unix timestamps.
  • order_by (“asc|desc”)Order results by date, ascending or descending.
  • limit (Int)Maximum number or results to return, upper limit 1000.
  • offset (Int)Skip a number of events. Used with limit parameter when paginating results.
  • count_only (1|0)If true, query returns only the number of results found with given parameters.

Return codes

200 OK

Successful GET responses.

201 Created

Resource created successfully. Check Location header field for new id. Response body will be empty.

204 No Content

Successful PUT and DELETE responses.


400 Bad Request

Invalid parameter(s), e.g. missing or of wrong type.

403 Forbidden

Client is not authorized to access resource.

404 Not Found

Requested resource cannot be found.

405 Method Not Allowed

HTTP method is not supported/recognized

411 Length Required

POST or PUT request length missing.

413 Request Entity Too Large

POST and PUT requests are limited to maximum size of 67108864 bytes.

429 Too Many Requests

Too many API calls per second. Check Retry-After header for cooldown time (in seconds).

495 Cert Error

Invalid client side cerificate.

496 No Cert

Certificate missing.

500 Internal server error

Unexpected fatal error, a bug.

503 Service Unavailable

The service is temporarily closed for maintenance or other reasons. Client should retry the request after a short period.