Registration Postbacks

Registration postbacks (commonly called “web hooks” in today’s terms) are a mechanism that allows SCORM Cloud to send registration updates directly from our system to yours. Postbacks are essentially the only way to reliably get near-real-time updates about registration state.

Configuring Postbacks

We offer ways to configure postbacks for the three major ways of creating registrations in SCORM Cloud. In each case, the same parameters are supported. Those parameters are described in more detail below.

  • Registrations that are created via the registration service’s createRegistration call have their postbacks configured directly in createRegistration. Postback settings for registrations can be changed by calling updatePostbackInfo.
  • Invitations support postbacks via the createInvitation and createInvitationAsync calls. When registrations are created for those invitations, they will be created with the postback settings specified in createInvitation(Async). Invitations don’t support changing postback settings on an invitation level, although the registrations’ settings can be changed via the regular registration API.
  • Dispatches support postbacks via the createDispatch call. Dispatches are different from regular registrations and invitations in that the postback settings are stored at the dispatch level. That is: if the postback settings for a dispatch are changed via updateDispatches, those settings will retroactively take effect for all registrations attached to that dispatch.

Testing Postbacks

When implementing postbacks, we recommend using the registration service’s testRegistrationPostUrl method to test your postback implementation. This API call will generate dummy data and POST it to the endpoint you specify. If it fails, it will return the reason for the failure.

See Postback Settings below for a description of the postback settings.

Caution

We consider 3xx status codes (like a 302 redirect) to be successful, as we can’t follow HTTP redirects for POST requests as per the spec. Make sure your system isn’t returning a 301 or 302 redirect for your endpoint, as it likely isn’t processing the actual data if so. This is especially common if your postbackurl is configured to be an HTTP URL and your system tries to redirect to HTTPS.

Error Handling

Postbacks were designed to be highly reliable. Our system uses a durable work queue built on top of Amazon Web Service’s Simple Queue Service (SQS).

When your system responds to our HTTP request, we consider any non-4xx and non-5xx status codes as success. Any response that has a 4xx or 5xx status code or any other general failure (like a connection timeout, DNS lookup failure, etc.) is treated as a failed request and will be retried later. (Note: postbacks sent via testRegistrationPostUrl do not use the work queue and will not be retried.)

We retry failed requests up to 70 times. After each unsuccessful attempt, we add a delay before the next retry. That delay follows an exponential backoff with jitter algorithm.

Specifically: we will always wait at least 1 second between attempts. We will wait a maximum of 15 minutes between attempts (an AWS SQS API limitation). Within those bounds, we will wait exponentially longer between attempts. This means that the first 5 retries will happen across the span of approximately 15-20 seconds. The remaining 60 retries will happen across the span of approximately 6-8 hours. After about 6-8 hours, our system gives up.

For a given registration, we only retry the most recently generated; postbacks don’t stack up for a single registration. Thus, when your system receives a postback successfully, it is always the latest registration state (not out-of-date data that failed earlier).

Postback Settings

To perform a postback, our system builds the registration state using the exact same format as getRegistrationResult and sends that data to your system – see Format (authtype) below for how that data is sent to your system.

Thus, the code to parse the getRegistrationResult API call and the code to parse the data from the postback we send you (once it’s decoded) are the same.

As stated above, postback settings in all three cases offer the same parameters:

postbackurl

The HTTP/HTTPS URL to which results data will be POSTed. We strongly recommend using HTTPS.

urlname

An optional login name that will be sent to the postback URL (see below for format information)

urlpass

An optional login password that will be sent to the postback URL (see below)

resultsformat

One of course, activity, or full; this is the same resultsformat parameter as in getRegistrationResult

authtype

One of form or httpbasic (default form), this parameter controls the format of how we send the getRegistrationResult data to your system. We recommend using form.

Format (authtype)

We recommend using the form authtype unless httpbasic is required.

form authtype

If the authtype is set to form (the recommended) or left blank, we will send a request to your endpoint with:

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

The body of that request will contain up to three URL-encoded parameters, as per that content type:

  • a username and password parameter, if both were set, and
  • a data parameter containing the URL-encoded getRegistrationResult XML

Here’s an example body sent to an endpoint with the form authtype:

username=testusername&password=testpassword&data=%3Cregistrationreport+format%3D%22course%22+instanceid%3D%220%22+regid%3D%22testregid%22%3E%3Ccomplete%3Ecomplete%3C%2Fcomplete%3E%3Csuccess%3Epassed%3C%2Fsuccess%3E%3Ctotaltime%3E224%3C%2Ftotaltime%3E%3Cscore%3E93%3C%2Fscore%3E%3C%2Fregistrationreport%3E

Note the three parameters (username, password, and data), with the data being URL-encoded XML.

Note

This request type ends up being the same as a simple HTML form submission – which makes it convenient for development. In PHP, these variables can be accessed via $_POST or $_REQUEST, for example.

httpbasic authtype

If the authtype is set to httpbasic, we will send a request to your endpoint with:

Content-Type: text/xml; charset=UTF-8

If the username and password are provided, they will be sent via typical HTTP basic auth in the request. That is, the username and password will be concatenated together (separated by a colon), then base64-encoded, and then put in the Authorization header. For example:

Authorization: Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA==

This is the authorization header for the username testusername with password testpassword, the same parameters as above in the form example. (That is, the above header is base64("testusername:testpassword") in pseudocode.)

The body of the request will be the URL-encoded getRegistrationResult XML. For example:

%3Cregistrationreport+format%3D%22course%22+instanceid%3D%220%22+regid%3D%22testregid%22%3E%3Ccomplete%3Ecomplete%3C%2Fcomplete%3E%3Csuccess%3Epassed%3C%2Fsuccess%3E%3Ctotaltime%3E224%3C%2Ftotaltime%3E%3Cscore%3E93%3C%2Fscore%3E%3C%2Fregistrationreport%3E

Note

The Content-Type text/xml is not strictly correct in this situation, but this is kept for backwards-compatibility. As a result, if your postback endpoint tries to automatically parse the “XML” in the request body without URL-decoding it (because the Content-Type is text/xml), it will fail with an error.