xAPI Learning Activity Webhooks

The Experience API (xAPI) is a learning technology interoperability specification that makes it easier for learning technology products to communicate with one another. In the context of LinkedIn Learning, xAPI can be used to track learning events in realtime. When an event takes place, LinkedIn will send an xAPI compliant HTTP POST payload to your webhook URL. The webhook URL & credentials are configured in LinkedIn Learning admin settings. To learn more about xAPI, review the Experience API (xAPI) Specification.

Authentication

LinkedIn Learning xAPI webhooks use two-legged OAuth 2.0 to send authenticated POST requests to your learning platform. Two-legged OAuth is also known as OAuth 2.0 Client Credentials Grant. Your Learning Platform is the authorization server and LinkedIn Learning is the client. LinkedIn Learning will authenticate with your Learning Platform directly in a system-to-system context. This section outlines the authentication request/response:

Access Token Request Reference

Request Details

URL Verb Headers
https://your-learning-platform.com/oauth2/token POST Content-type=x-www-form-urlencoded
Request Body Parameters
Parameter Description Required
grant_type Value will always be client_credentials Yes
scope Supported values are xapi:read, xapi:write and xapi:all. LinkedIn Learning will request the xapi:write scope. Yes
client_id Value should be obtained from your learning platform Yes
client_secret Value should be obtained from your learning platform Yes
Sample cURL Request
curl -X POST https://your-learning-platform/oauth2/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials&client_id=dunder_mifflin&client_secret=abc123def45&scope=xapi:write'

Access Token Response Reference

Response Details
Status Headers
200 Content-Type: application/json;charset=UTF-8
Response Body
Item Value
access_token Valid access token string
expires_in Time to live (TTL) in seconds
token_type Value should always be "bearer"
Sample Response
{
  "access_token":"2YotnFZFEjr1zCsicMWpAA....",
  "token_type":"bearer",
  "expires_in":3600
}

Activity Statement

A learner activity webhook POST body follows an Actor, Verb, Object data model. This section describes each object in the data model. For additional details, review the Experience API Data section of the specification. LinkedIn will report the following two activities to your LMS system:

  • COMPLETED -- sent when the learner/actor has completed a course.
  • PROGRESSED -- sent when the learner/actor has completed a video in a course.

Completed Statement POST Body example

Here is an example COMPLETED statement request POST body. This statement would be sent after actor dschrute@linkedin.com completes course urn:li:lyndaCourse:563463.

{
    "actor": {
        "mbox": "mailto:dschrute@dundermifflin.com",
        "objectType": "Agent"
    },
    "result": {
        "duration": "PT1M22S",
        "completion": true
    },
    "verb": {
        "display": {
            "en-US": "COMPLETED"
        },
        "id": "http://adlnet.gov/expapi/verbs/completed"
    },
    "id": "e45018e3-e91f-47a1-b003-5938e4db4a8c",
    "object": {
        "definition": {
            "type": "http://adlnet.gov/expapi/activities/course"
        },
        "id": "urn:li:lyndaCourse:563463",
        "objectType": "Activity"
    },
    "timestamp": "2018-09-17T19:13:27.384Z"
}

Progressed Statement POST Body example

Here is an example PROGRESSED statement request POST body. In this example a statement is sent after actor dschrute@linkedin.com completes a video in the course urn:li:lyndaCourse:2822089 in LinkedIn Learning.

{
    "actor": {
        "account": {
            "homePage": "https://example.com",
            "name": "dschrute@linkedin.com"
        },
        "objectType": "Agent"
    },
    "id": "b2f642cb-5a65-4b15-a1ae-887f1099a4e1",
    "object": {
        "definition": {
            "type": "http://adlnet.gov/expapi/activities/course"
        },
        "id": "urn:li:lyndaCourse:2822089",
        "objectType": "Activity"
    },
    "result": {
        "completion": false,
        "extensions": {
            "https://w3id.org/xapi/cmi5/result/extensions/progress": "28"
        }
    },
    "timestamp": "2020-04-16T21:27:19.996Z",
    "verb": {
        "display": {
            "en-US": "PROGRESSED"
        },
        "id": "http://adlnet.gov/expapi/verbs/progressed"
    }
}

Activity Statement: Sample cURL

curl -X POST \
  https://your-learning-platform.com/xAPI/statements \
  -H 'Authorization: Bearer AyOtu...' \
  -H 'Connection: close' \
  -H 'Content-Type: application/json' \
  -H 'X-Experience-API-Version: 1.0.0' \
  -d '{
    "actor": {
        "mbox": "mailto:dschrute@dundermifflin.com",
        "objectType": "Agent"
    },
    "result": {
        "duration": "PT1M22S",
        "completion": true
    },
    "verb": {
        "display": {
            "en-US": "COMPLETED"
        },
        "id": "http://adlnet.gov/expapi/verbs/completed"
    },
    "id": "e45018e3-e91f-47a1-b003-5938e4db4a8c",
    "object": {
        "definition": {
            "type": "http://adlnet.gov/expapi/activities/course"
        },
        "id": "urn:li:lyndaCourse:563463",
        "objectType": "Activity"
    },
    "timestamp": "2018-09-17T19:13:27.384Z"
}'

Actor

The actor object identifies the learner who performed an action in LinkedIn Learning. The functional identifier value used in activity statements is configurable in Linkedin Learning admin settings. There are two supported options:

  1. SAML SSO User Identifier: User identifier value included in SAML SSO authentication payload. This value can be an email address, username, employee number or any other unique and immutable user identifier. If your learning platform is configured as a SAML IdP select this option. If a third party identity management system is in use, this option can be used if both relying parties (LinkedIn Learning & your learning platform) are configured to receive the same user identifier from the SAML IdP.
  2. Email: A learner's work email address value.

Actor: SAML SSO User Identifier Example

"actor": {
    "account": {
        "name": "dpappas",
        "homePage": "https://linkedin.com/learning"
    },
    "objectType": "Agent"
}

Actor: Email Identifier Example

"actor": {
    "mbox": "mailto:mscott@dundermifflin.com",
    "objectType": "Agent"
}

Result

The result object represents a measured learning outcome. The completion field indicates whether or not the LinkedIn Learning course was completed in full and duration is the period of time over which the completion took place. Durations are expressed using the format for Duration in ISO 8601:2004(E) section 4.4.3.2.

Example when course is completed

"result": {
    "duration": "PT1M22S",
    "completion": true
}

Example when course is not completed

"result": {
        "completion": false,
        "extensions": {
            "https://w3id.org/xapi/cmi5/result/extensions/progress": "28"
        }
}

Verb

The verb object identifies the event triggered in LinkedIn Learning. The supported verbs are COMPLETED and PROGRESSED. The events are fired when a user completes a LinkedIn Learning course for COMPLETED statements and when a video is completed for PROGRESSED statements.

Verb: Completed Example

"verb": {
    "display": {
        "en-US": "COMPLETED"
    },
    "id": "http://adlnet.gov/expapi/verbs/completed"
}

Verb: PROGRESSED Example

 "verb": {
    "display": {
        "en-US": "PROGRESSED"
    },
    "id": "http://adlnet.gov/expapi/verbs/progressed"
}

Object

Object identifies a course on LinkedIn Learning. The object.id URN value is a unique identifier whose value should be treated as opaque. The object.id value is synonymous with course URN values returned in the /learningAssets API response body.

Object: LinkedIn Learning Course Example

"object": {
    "definition": {
        "type": "http://adlnet.gov/expapi/activities/course"
    },
    "id": "urn:li:lyndaCourse:563463",
    "objectType": "Activity"
}

Retry Behavior for xAPI Events

Note

Retry behavior is only utilized for completion events, not progress statements.

In order to send an xAPI event to an external system, a multi-step process is initiated to request an OAuth2 access token and then send the xAPI event using the access token. If an error status code is encountered in either HTTP request, or any other failure is encountered at any time during this process, the event is enqueued and retried at a later time. Status codes 300 and above will result in a failed attempt, only 2XX level status codes are considered successful. The retry cadence may change over time, but today the current behavior retries sending xAPI events that have failed every 12 hours for 5 days.