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
, orfull
; this is the same resultsformat parameter as in getRegistrationResult
authtype
One of
form
orhttpbasic
(defaultform
), this parameter controls the format of how we send the getRegistrationResult data to your system. We recommend usingform
.
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
andpassword
parameter, if both were set, and - a
data
parameter containing the URL-encodedgetRegistrationResult
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.