integraion icon

Integrations

This page lists the existing client plugins integrating various systems with our API.

If you’ve created something awesome you’d like to share, tell us all about it! Contact us at contact@openbadgefactory.com and we’ll add your app to the list.

Mahara (mahara.org)

Moodle (moodle.org)

Totara (www.totaralms.com)

Wordpress (wordpress.org)

LTI Integrations

Open Badge Factory LTI Integration provides a link between an LTI supported LMS and Open Badge Factory. Currently we offer BlackBoard and Canvas LTI integration.

Read more about the features of Open Badge Factory LTI integration

Installation guides and instructions


Open Badge Factory REST API

Client side certificates

We use X.509 client side certificates to authenticate you and authorize API calls. The procedure for creating your certificate is as follows:

1. Get your API key

Login to OBF as a user in admin role and got to Admin tools > API key. You need this token for generating your certificate signing request. The generated token will be valid for ten minutes. After that it cannot be used for certificate signing.

2. Get our public RSA key
GET https://openbadgefactory.com/v1/client/OBF.rsa.pub
3. Decode your API key with our public key

in Perl:

my $key = Crypt::OpenSSL::RSA->new_public_key($pubkey);

$key->use_pkcs1_padding;

my $decrypted = $key->public_decrypt( decode_base64( $apikey ) );

my $json = decode_json($decrypted);

in PHP:

$key = openssl_pkey_get_public($pubkey);

$decrypted = '';

openssl_public_decrypt( base64_decode($apikey), $decrypted, $key, OPENSSL_PKCS1_PADDING );

$json = json_decode($decrypted);
4. Generate your Certificate Signing Request with your decoded API key

API key JSON object has the following structure:

{
  "id":      "...", // your client id
  "subject": "...", // your certificate subject line
  "ctime":   "...", // timestamp
  "nonce":   "..."  // security nonce
}

Id parameter is your client id in OBF. Save it for later use.

Use the subject parameter as the subject line in your CSR. (Command line OpenSSL used in this example.)

$ openssl req -new -nodes -batch -days 1095 -newkey rsa:2048 -keyout /tmp/obf-test.key -subj '$PAYLOAD_SUBJECT' > /tmp/obf-test.csr
5. Send your CSR for signing
POST https://openbadgefactory.com/v1/client/{$client_id}/sign_request

{
    signature => "...",
    request   => "..."
}

Make a POST request with a JSON string as body content. Signature parameter is the base64-encoded api key you got from our admin panel (in step 1.) Just send it back as-is, without changes.

Request parameter is your certificate signing request file contents. Successful signing operation will have return code 200 OK and the response body contains your new certificate.

6. Store your certificate and private key for future use

You need your certificate and private key with every API call. Store the files securely and grant appropriate file system permissions.

Also, remember to save your client id.

7. Test your keypair
GET https://openbadgefactory.com/v1/ping/{$client_id}

Successful request will have return code 200 OK and the response body echoes back your client id.

Check your platform docs for the usage of client side certificates. Here are couple of examples.

Perl, with LWP:

my $ua = LWP::UserAgent->new;

$ua->ssl_opts(
    SSL_verify_mode => 'SSL_VERIFY_PEER',
    SSL_key_file    => '/path/to/your/private.key',
    SSL_cert_file   => '/path/to/your/certificate.pem'
);

my $res = $ua->get('https://openbadgefactory.com/v1/ping/' . $client_id);

# Expected results:
#   $res->code    == 200
#   $res->content eq $client_id

PHP, with cURL:

$ch = curl_init();

$options = array(
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_HEADER         => false,

    CURLOPT_URL     => 'https://openbadgefactory.com/v1/ping/' . $client_id,
    CURLOPT_SSLCERT => '/path/to/your/certificate.pem',
    CURLOPT_SSLKEY  => '/path/to/your/private.key',
);

curl_setopt_array($ch , $options);

$result = curl_exec($ch);
$info   = curl_getinfo($ch);

curl_close($ch);

/*
* Expected results:
*   $info['http_code'] == 200
*   $result == $client_id
*/

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 badge

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

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

Delete 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 badges

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.

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}/?email=foo@example.com

DELETE /v1/event/{client_id}/{event_id}/?email=foo@example.com|bar@example.com|quux@example.com

Return code: 204 No Content

Get revoked badges:
GET /v1/event/{client_id}/{event_id}/revoked

Sample output:

{
    "revoked": {
        "foo@example.com": 1434971021, // recipient email address and revocation timestamp
        "bar@example.com": 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. Required.

email (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 assessment

reviewer (String)

Reviewer’s identification string

expires (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.

Reports

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.

Errors

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.