SCORM Cloud
API Documentation

Introduction

Thanks for the interest in SCORM Cloud! This document should serve as a good starting point for integrating the service into your own system. What you'll find below is a brief conceptual overview, an outline of the key steps in running a minimal SCORM Cloud integration (which includes links to a demo application written in .NET), and a full listing of the SCORM Cloud web services API.

Conceptual Overview

Before you read any more, we should let you know we're assuming a couple things about you. (Don't worry, it's nothing personal, so don't take it personally.) Firstly, we assume you have a basic idea of what SCORM Cloud is. If not, we have some excellent starting points for you on the SCORM Cloud page of our website. Secondly, with the first assumption out of the way, we assume that the key goal of you, the reader, is to integrate SCORM Cloud into your own system, with the ultimate goal of leveraging the benefits and adding the value of SCORM compatibility to your product or service. Another assumption we're making is that you are a developer, or at least technically proficient, and that you are familiar with ideas like web services, software as a service, and have some experience in or knowledge about programming and developing software.

At this point, you probably already know that SCORM Cloud is a hosted player that provides best-in-class SCORM compatibility. You may or may not already know however, that this player and the data that it uses can be accessed and manipulated programmatically over the web. (Neat, right?!) Taking this a step further, this programmatic access has been exposed with the goal of allowing you to build SCORM compatibility into your own system, and we provide varying levels of customization (based on your willingness to tackle the technical details.) This integration, in it's simplest form, would mean that your system will use the web services to import SCORM content to our servers, create registrations for this course for your users, launch those registrations by directing the user to our player, and finally collect and analyze the results of their learning experience. (We'll show how to do each of those things below in the Quick Start section.)

No matter how simple or complex, the key concept of a successful integration with SCORM Cloud is that your system and SCORM Cloud should be tightly integrated, but loosely coupled. The SCORM Cloud services work best when they are tied together with your system at a data level via courseId / learnerId / registrationId, and there is a one to one correspondence of courses, learners, and registrations in our system and your own. This means that the basic entities that you create / register in SCORM Cloud should always exist in your own system as well as ours. There is good reason to bias an integration with SCORM Cloud towards this style / architecture, because it allows much more flexibility over time on just how you would like things to work with your user and course data.

While we have service calls that fetch data (in addition to registering data), and we may, in the future, take on the responsibility of keeping more user information, it will only be able to serve limited purposes and hold only limited information, since we can't add any custom field asked of us. But if the user / course / registration information you need is kept in your system, you can evolve the data and behavior of that entity in your system in any way you'd like over time, and simply tie that entity to SCORM Cloud via the learnerId / courseId / registrationId. On the other side of that boundry or tie, we can evolve the data and behavior of the learner's data and experience as it pertains to taking the actual course, and tracking and reporting their registration data (score, completion, success, total time, the way the learner took the course, the answers they gave to certain questions, and much more). In the case of integration with our API, a bias towards "owning" most of the data in your learning system will leave you in more control over time, and allow your custom logic to shine, and you'll only need a few small well defined integration points to SCORM Cloud to take advantage of what we do best, which is provide a stellar SCORM player and track useful / compelling reporting data to go along with it.

Quick Start

Signup

First, the SCORM Cloud service needs to know who you are. Have you already signed up for an account? The trial is free, and exploring the features provided in the website is a great way to get to know our product before bringing some of those features into your own system. Let’s assume that’s all done and you know what you’re getting into.

What you need for identification, at a technical, web service level, is what we call an AppId. That’s short for Application Id, which is really all that our web service wants to know about you (don’t take offense, it’s just that it doesn’t like mixing personal details in with business, you know). You get one of these AppId’s at signup, and you can also create more yourself. To see them, check out the “Apps” page in your SCORM Cloud account online (you can access the page with the “Apps” button on the left side menu).

The idea here is that for each Application you may integrate with SCORM Cloud, you’ll have a different AppId, so that you can keep track of the relationship of data from your application to ours. So what you’ll want from the Apps page, whether you’d like to use the default one provided or create a new pair, is an AppId and the SecretKey that goes along with it, which you’ll use to identify your system. Oh, and of course you’ll also want to know where the web services actually live, which is at http://cloud.scorm.com/api. (Sometimes you’ll see this last piece of info, the web service location, called the ServiceURL in code, only without the api, such that the client will be configured with a ServiceURL of simply http://cloud.scorm.com).

Download

The services for SCORM Cloud are provided in your application code via a client library, which are currently available for .NET, Java, and PHP, and can be downloaded here on the SCORM Cloud development homepage. Below, we'll also reference the .NET Demo Application for examples, which you can also download at the SCORM Cloud development homepage or directly from this support forum post. (In the case of the .NET demo application, you'll want the .NET client library, which is packaged with the demo application). The very first thing you'll want to do is make sure you've got the client library available in your application code (for a .NET application, this is done either by bringing the project into your VS solution or referencing the compiled DLL for it).

Initialize

Once you're ready to use the library in your application, the first step is to make sure it is configured when your application initializes. (In the demo app, this is done in the Application_Start method in the file Global.asax.cs. There we set the AppId, SecretKey, and Services Url for the client library, so that it knows where to access SCORM Cloud services and what account to access them under.) In your own application, at initialization time, you'll want to do something like this:

	ScormCloud.Configuration = new RusticiSoftware.HostedEngine.Client.Configuration([your services url], [your app id], [your secret key]);

Once the library is configured, you don't have to worry about those values anymore and you can start calling methods and interacting with SCORM Cloud. Here's how you'd do so...

Import

The client libraries include an easy to use call that simply takes the path to a course zip on the calling machine, like so:

	ScormCloud.CourseService.ImportCourse([your course id here], [absolute path to course zip here]); 

We ask the user to specify the course id in order to allow them to attach it to meaningful data in their own system. Normally this means the creating the record for the package in your own system first, then importing into ours, and conditionally rolling back if necessary. Below is some pseudo code that reflects this practice:

	... file to import is present on your server (has been posted from the user or otherwise) ...
	... the absolute path to this file is called filepath below ...
	
	courseid = fetch_new_course_id()
	title = POST['title']  
	difficulty = POST['difficulty']  //this is just an example of a field that might
	                                 //be specific to your system, SCORM Cloud doesn't know
	                                 //or track difficulty
	
	add_course_to_local_system(courseid, title, difficulty)
	try:
	    ScormCloud.CourseService.ImportCourse(courseid, filepath)
	catch error:
	    remove_course_with_id_from_local_system(courseid)
	    report_error(error)
	

In the psuedo code above, the difficulty field is an example of a field specific to your own system. By tying your local record to a the package you import with SCORM Cloud using the courseid parameter, you can keep track of and organize your SCORM packages using any custom logic you can come up with in your own system, and only worry about SCORM Cloud when it comes time to reference the course in other SCORM Cloud API calls, like when previewing or creating registrations against this course.

Create Registration

Once the course is imported, you can use the course id in subsequent library calls to create registrations for the course. (In the demo app, we create registrations when sending out the invitation to a course. You can see the call in SendLearning.aspx.cs around line 82 or so.) The simplest version of this call looks like this:

	ScormCloud.RegistrationService.CreateRegistration([registration id], [course id], [learner id], [learner first name], [learner last name]);

Again, each id supplied to this call should coincide with a record in your own database, to which you might attach more data, or which you can later use to look up information about the course/registration at a later time.

Launch Registration

Now, with a registration created against our course, we can launch that registration, by redirecting the user's browser to the location returned by ScormCloud.RegistrationService.GetLaunchUrl. There is one caveat here, which is that this URL should be fetched moments before the user is redirected, as opposed to generated and placed on a link on a page where it might sit for some time. (In the demo app, we have a link that points to Launch.aspx, which in turn does the above and fetches the launch URL from ScormCloud.RegistrationService.GetLaunchUrl, then redirects the user.) In it's simplest form the code looks like this:

	String launchUrl = ScormCloud.RegistrationService.GetLaunchUrl([registration id], [redirect on exit url]); 
	Response.Redirect(launchUrl);

Above, the registration id should refer to a registration that you've created, and the redirect on exit url parameter should point to the URL you would like the user to end up at when the course exits. The other idea behind the redirect on exit url parameter is to use that location as an opportunity to fetch the registration information, such as completion, success, score, and total time spent in the course. To do that, you can add the registration id onto the end of the redirect on exit url, and it will be available as a parameter when the user exits the course and goes to that location.

Fetch Registration Results

At any rate, you'll want to fetch some information about the registration when it has completed, in order to do any sort of reporting about them. You can get the "big four" pieces of data referred to above (completion, success, score, total time) by making a call to GetRegistrationSummary. (We do this in the demo app in LearningSent.aspx.cs around line 54.) The simplest version of this call looks like this:

	RegistrationSummary summary = ScormCloud.RegistrationService.GetRegistrationSummary([registration id]);

You'll typically want to save the summary data into your own database, so that you can refer to it when reporting, as opposed to fetching the summary for registrations every time from us over the network, which can be very slow. As noted above, the best practice here would be to include the registration id as a parameter on the redirect-on-exit URL (specified at launch time), and then using the above call to GetRegistrationSummary using that registration id parameter. That way you can fetch the results right then when the user exits and feel assured that what you fetched is also what we have recorded.

Explore

That's the basic path to import, register, and launch. But the SCORM Cloud API exposes a lot more functionality beyond the basics. And beyond the API, other possibilities are open by using the site we've built on top of the service, which you can find by pointing your browser at http://cloud.scorm.com. Also, if you're looking to explore our reporting application, Reportage, alongside the SCORM Cloud API, make sure you check out the Reportage Integration Documentation as well . Let us know what you think, and what you discover as you explore further by sending an email to support@scorm.com.

Below you'll find the technical details of the SCORM Cloud web service API, along with a full listing of the available methods we expose. The details and format of the communication with our web services is largely abstracted by our client libraries, which attempt to provide the remote services as local method calls. However, as the API expands, you might find that the client library you're using is missing one of the calls below you'd like to use. In this case, our advice is, give a try at implementing it! Since the calling format is always the same, it's pretty easy to copy the calling mechanism from another method, and while most of the XML formats of results differ between calls, parsing them is very similar. If you make a change you think we should know about, please let us know! We'd love to get your help in making the client libraries and the web services even better!

Web Service Communication Format

This section exposes some of the more "nitty gritty" details of our web services, which are normally hidden by the client libraries we've made available. If you're looking to see what's going on under the hood of those libraries or you wish to create your own (or extend an existing library), you'll want to familiarize yourself with this section.

All web service calls (through the current interface) are of the form http://cloud.scorm.com/api?method=[service.prefix].[methodName]&appid=[your app id]&origin=[your origin string](&any=other&methodparams=here)(&security=params)

For secured services (which will likely be all services offered), the security params include the ts param (a UTC timestamp of the form yyyyMMddHHmmss) and the sig param (an MD5 hash signature of the method call, detailed below)

Each http request sent to a secured web services instance must contain the following parameters to pass the security check:

The origin string parameter must not contain spaces or any other special URL characters and should be in the format of:
    [company/organization].[application name].[application version]
All characters in the organization and application names should be lowercase with spaces removed. Versions can contain periods and dashes.
For example, "Rustici Software SCORM Cloud 2.0 Beta" would be represented as:
    rusticisoftware.scormcloud.2.0-beta

The signature ("sig" param) is created using the following algorithm:

The resulting hex string is the signature for the method call and is attached as the sig parameter (e.g. api?method=[method]&appid=[appid]&ts=[timestamp]&sig=7D6AED5AD524170A018D4AC8FFE0693C) The server will perform the same operations listed above and allow access if the signatures match.

The timestamp sent in the request must match the time on the server (within an expiration limit). In this way, every service request (over time) is uniquely signed, even if the same parameters are used in the call.

Every web service call should result in a formatted response. The current implementation defaults to using a rest XML format similar to the flickr api. A typical "successful" response will be of this form:

<?xml version="1.0" encoding="utf-8" ?>
	<rsp stat="ok">
	    [xml payload]
	</rsp> 

And a typical "error" response (usually caused by an error or exception in performing the requested operation) should have the form:

<?xml version="1.0" encoding="utf-8" ?>
	<rsp stat="fail">
	    <err code="[error code here]" msg="[error message here]" />
	    [*potentially <err code="[inner exception error code]" msg="[inner exception message]" />]
	    [*optionally
	     <errordetails>
	          <stacktrace>
	               <tracetext>text</tracetext>...
	          </stacktrace>
	     </errordetails>]
	</rsp>

The error return can optionally include an errordetails element that includes extra diagnostic information (like a stack trace). This is enabled by a configuration variable in the web service core code. Perhaps it should be a common optional parameter to pass to any method...


There are a number of common error codes that can be returned by all available methods, which are as follows:

Common error codes:

Error codes 0-99 specify errors that have occurred during processing of a web service call. Error code 99 is reserved to note "general errors", which refer to exceptions that are thrown in processing that are not handled by the web service in a more specific way.

In the service call specifications below, the example response will show just the xml payload that is wrapped in a successful <rsp> element as shown above. Similarly the error codes and messages noted for each method will be wrapped in the common error response format shown above.

Useful Integration Concepts

Understanding Course Versioning

Course versioning is conceptually similar to other versioning systems you use, like GoogleDocs, wikis, websites, code versioning systems, and so on. By creating a new version of a course, you'll maintain a snapshot of the course content as a previous version, and keep historical data regarding that version as well. To create a new version of an existing course, just call importCourse with a courseid that refers to the course you'd like to update. At it's simplest form, that's really it. New registrations will then be launched against the newest available version of the course. You can see information about these versions and instances using the getCourseDetail and getRegistrationDetail web service calls.

The only tricky part that merits more explanation is how we'll handle existing registrations that are registered against the course. In an ideal world, we'd simply carry over existing registration data from the current version to the new version of the course and start the user on the new version seamlessly. Unfortunately it's not quite that simple. Because course information and structure can change freely when importing a new version, the course structure and indeed the semantics of the course itself can change. However, registrations contain information that is structured closely around the course structure. Because the decision about how to represent the previous structure in the new structure can't be made in every arbitrary case, we instead provide another concept for 'versioning' registrations, called 'instancing'.

Using registration instancing, we'll maintain a historical record of every registration for each version of a course it's been launched against. You'll still be able to dig up and report on that historical data. When you upload a new version of a course, you'll have the option to choose when we should create a new 'instance' of the existing registrations, leaving behind a historical record of the user's progress on their current version and restarting them on the newest version of the course. When this happens, for the user, it will appear they've restarted at the beginning of the course, but now on the new version.

API Listing

Debug Service   (rustici.debug)

This service provides a very basic set of simple method calls to check the status of a running web service instance.

ping

authPing

getTime

Course Service (rustici.course)

This secured service allows for many operations related to courses, including importing new courses and retrieving information about imported courses.

importCourse

importCourseAsync

getAsyncImportResult

preview

properties

exists

getAssets

updateAssets

deleteCourse

getFileStructure

deleteFiles

getAttributes

updateAttributes

getMetadata

getManifest

getCourseList

getCourseDetail

Registration Service (rustici.registration)

This service provides calls for creating and removing registrations, and launching existing registrations.

createRegistration

deleteRegistration

resetRegistration

getRegistrationList

getRegistrationDetail

getRegistrationResult

getRegistrationListResults

launch

getLaunchHistory

getLaunchInfo

resetGlobalObjectives

updateLearnerInfo

testRegistrationPostUrl

Invitation Service (rustici.invitation)

This service provides calls to create and enable/disable SCORM Cloud invitations as well as for retrieving information about invitations.

createInvitation

createInvitationAsync

getInvitationStatus

getInvitationInfo

getInvitationList

changeStatus

Tagging Service (rustici.tagging)

This service provides the ability to add and remove tags from learners and courses. 

getCourseTags

setCourseTags

addCourseTag

removeCourseTag

getLearnerTags

setLearnerTags

addLearnerTag

removeLearnerTag

getRegistrationTags

setRegistrationTags

addRegistrationTag

removeRegistrationTag

Reporting Service   (rustici.reporting)

This service provides a set of methods for accessing information about or owned by the account designated by the appid, and ties in with the Reportage reporting application. For more information about accessing Reportage, check out the Reportage Integration Documentation.

getAccountInfo

getReportageAuth

launchReport

Dispatch Service (rustici.dispatch)

This service provides an interface to SCORM Dispatch, a tool used to deliver SCORM content from SCORM Cloud to client LMSs in the form of a simple and highly compatible SCORM 1.2 package. The three important entities to keep in mind when using the API are Course, Dispatch Destination, and Dispatch. A course is any host course that has been imported under your AppId. A dispatch destination should map to clients or locations where you'll be sending your dispatches. In this way, dispatches can be enabled or disabled (or downloaded) per client / location. Finally, a dispatch represents the intersection of a course and destination, and has the downloadable output of a simple SCORM 1.2 package that can then be launched at the given destination. The dispatch package does not contain the course assets of the target course, it just gives access to the package hosted on SCORM Cloud. A dispatch can be enabled or disabled at any time, even after deployment of the dispatch packages, allowing a system of centralized access for the dispatch creator.

getDestinationList

getDestinationInfo

createDestination

updateDestination

deleteDestination

getDispatchList

getDispatchInfo

createDispatch

updateDispatches

downloadDispatches

deleteDispatches

Export Service (rustici.export)

This service provides a simple interface to request an export of the user data created on the SCORM Cloud. This data includes all the metadata and object xml for every course and registration.

start

cancel

status

download

list

Get Support

As always, if you have any questions, please shoot them over to us at support@scorm.com and we'll do our best to clear up any gray areas. We'd love the opportunity to use your feedback to make our documentation, service, and site even better!