On Demand xAPI Registrations

The On Demand xAPI Registrations feature provides the means to accept xAPI statements and have them reflected in registrations much like launched content would be, without needing to create those registrations ahead of time.

This is done by adding a new configured instance of ContentConnector.OnDemandRegistrations.Xapi to define which statements should be mapped to registrations, and how the registration (and course and learner) IDs should be set based on those statements, see: how to create a content connector instance. Although this doesn't provide the search and import capabilities most content connectors do, it is configured in the list of content connectors.

Once configured, regular expressions are used to filter activities via ID or activity type, and actors via ID that should cause a statement to be mapped to a registration. Templates for the registration, course, and learner to use for the statement are configured using tokens from the matched activity IDs or types, or the matched actor. The generated ID can then optionally be used in an API call back to your system to determine the final ID to use. Finally, the resulting ID can either be used as is or hashed.

Consider the following configuration:

    "contentConnectorType": "ContentConnector.OnDemandRegistrations.Xapi",
    "configuration": {
        "xapiFilters": [
                "shouldApplyToRollupMappedStatements" : true,
                "actor": {
                    "account": {
                        "pattern": "(.*)@http://example\.org",
                        "caseSensitive": true
                "activity": {
                    "activityId": {
                        "pattern": "http://example\.org.*"
                    "activityType": {
                        "pattern": "http://adlnet\.gov/expapi/activities/course"
                    "onlyMatchObject": true
                "ids": {
                    "course": {
                        "idTemplate": "course_${ActivityId}",
                        "shouldHashId": true
                    "registration": {
                        "idTemplate": "${Actor_1}~~${ActivityId}",
                        "callbackUrl": "https://example.org/regcallback"
                    "learner": {
                        "idTemplate": "${Actor_1}"
    "enabled": true

With this configuration, statements will be selected that have an actor using an "account on a system" with a homepage of "http://example.org" and that also have an activity with activity type "http://adlnet.gov/expapi/activities/course" and ID starting with "http://example.org", but only if that activity is the object of the statement. These selected statements will be mapped to registrations.

The registration ID to map them to will be built by combining the first match group in the actor (the part before "@http://example.org") with the literal characters "~~" followed by the whole matching Activity ID. The resulting ID will be sent to "https://example.org/regcallback", which will respond with the actual ID to use and how long in seconds that mapping of "generated ID" to "actual ID" is good for. Finally the ID that was returned from that callback will be used as the actual registration ID.

The package and learner IDs will also be determined at this time. They will only actually be used in the case the registration needs to be created. If the registration already exists the course and learner for the existing registration will be assumed to be correct and not checked. Note that with this configuration the learner ID will be the first group of the Actor match, and no callback or hashing will be done. The course ID will be the full matched activity ID with the prefix "course_", hashed.

Statements with a result object will be rolled up just as if they were sent from launched content, unless "shouldApplyToRollupMappedStatements" is set to false. If the registration is created by this batch of statements, a rollup postback will be generated even if there are no results. So systems receiving rollup postbacks will find out about created registrations right away, even if there are no results to roll up.

Multiple filters can be defined, and that they are applied in order. This is inmportant for capturing statements that should be mapped to a registration but should not be rolled up, a filter with "shouldApplyToRollupMappedStatements" set to false could go first and capture such statements (possibly setting "onlyMatchObject" to false as well in order to find statements related to the activity being matched but not actually about it). Then a second more specific filter can be set, and if it matches it will override the first one.

results matching ""

    No results matching ""