Automated Post Feedback with Webhooks

When a learner creates or shares a learning artefact within an OpenLearning course, this creates a post. A post's content is determined by the widget from which it is created. This may be text, uploaded files, media such as images or video, or any other embedded content authored within integrated interactives.

OpenLearning provides the ability to automatically provide feedback on posts by setting up your own webhook service.


Use Cases

  • Running automated tests on learner submissions (e.g. running a test suite on code submissions)
  • Automated checking of learner submissions (e.g. plagiarism detection, grammar/language checking, keyword checking, automarking, or validation processes)
  • Generating reports, dashboards/scoreboards, or other outputs based on learner submissions (e.g. showcasing the output - as well as the code, of code submissions)
  • Pushing/publishing learner submissions to other systems
  • Updating the completion of the widget based on the value of the post



When a post is created by a learner, a request will be made to the webhook which can in turn make a request back to OpenLearning with additional information to add to the post. This can affect the post in the following ways:

  1. Adding a "Stamp" to the Post, which in turn may provide:
    • A feedback status, with either an "error", "pending", or "success" icon
    • A feedback message, as text displayed in any chosen colour
    • A link to further feedback information, such as a report
    • A score, as either a number or as both a numerator and denominator, displayed in any chosen colour
    • How to display the score, as either a number or a pie chart
  2. Adding additional feedback media to the Post, which may be:
    • text,
    • audio,
    • video,
    • image, or
    • an iFrame embedded web page
  3. Specifying who can see the above:
    • Teachers/staff only
    • Author of the post (+ course staff)
    • Entire class
  4. Setting a different thumbnail image for the Post, as displayed in galleries/feeds



Under Institution Settings > Integrations > Widget integrations select Add widget integration.

and then select: Webhook


Give the integration a name that helps you to identify it, and then enter the endpoint URL for your webhook service, and a secret key (recommended 32 to 64 characters).

If a secret key is left empty, no authentication will be used.


Courses under this institution can then add this integration to supported widgets within courses.

In the authoring mode of a course page, supported widgets will show a "Integrations" tab:


This integrations tab will allow you to select the newly added integration. Webhook integrations added to a widget also have an optional ability to override the endpoint URL on a per-activity basis. This can be left empty to use the previously configured webhook URL.


Webhook Integration

When a learner makes a Post on OpenLearning from a webhook-integrated sharing widget, the following POST request is made to the configured Webhook URL with the data of that Post:

Content-Type: application/json
X-OL-Signature: XXXXXXX (signed with webhook_secret)
  "url": "https://webhookurl.example.com/...",
  "token": "JWT as below",
  "user": "OL User ID",
  "name": "OL User Full Name",
  "post": {
    "id": "POST ID",
    "sourceBlock": "Block ID (posted from)",
    "sourceUrl": "Page URL (posted from)",
    "text": "Post 'thoughts' text",
    "data": { object containing learner's post data },
    "type": "Type of post",
    "createdAt": Seconds since unix epoch (time of issue),
  "class": "Class ID",
  "course": "Course ID",
  "returnUrl": "OpenLearning endpoint URL for sending back data"

The X-OL-Signature header is a SHA256 HMAC based on the Webhook Secret Key and the entire body of the request. If the secret key was left empty, no X-OL-Signature header is generated.

The “token” field is generated as a JWT. This token must be provided with the request back to OpenLearning for authentication.


When your external service receives the above request, it determines the authenticity of the request by also generating a SHA256 HMAC signature using its own copy of the Webhook Secret Key and the body of the received request. It then compares these two signatures (in constant time) to detect a match.

Once determined to be authentic, your service can then run what it needs to, and then send a PUT (or POST) request back to OL. The return request looks like:

Content-Type: application/json
X-OL-Signature: XXXXXXX
  "token": "JWT",
   ... return data

Where the X-OL-Signature header is again a SHA256 HMAC signature of the request body, generated using the Webhook Secret Key. No Signature header is required if the Shared Key is empty.

Return data consists of:

  • status: either “error”, “success”, or “pending”, (specifies the icon to use)

  • score (optional): information about the score, if one is to be displayed

    • value (number)

    • max (number, optional)

    • type ("score" or "pie", optional)

    • color (string, optional)

  • text (optional): text status to provide

    • value (string)

    • color (string, optional)

  • link (optional): a link to a report, the results of the integration, or additional information

    • text (string)

    • url (string)

  • feedback (optional): embedded content to display alongside the artefact, array of:

    • type ("iframe", "image", "text", "audio", "video", optional)

    • title (string)

    • url (string, present if type == "iframe")

    • text (string, present if type == "text")

    • caption (string, present if type == "image")

  • visibility (optional): who can view the stamp, defaults to “class” but can also be set to “author” (which also includes staff) or just “staff”

  • thumbnail (optional): the gallery/feed thumbnail image URL to use for this post

An example JSON body is as follows:

  "token": "JWT",
  "timestamp": 123456, // Integer ordering timestamp (e.g. seconds since epoch), must be larger for more recent requests
  "status": "error", // can also be "pending" or "success". This determines which icon to use on the stamp
  "score": {
    "value": 5, // a numeric score
    "max": 10, // optional, a maximum score
    "type": "score", // optional, can also be "pie" for a pie chart; defaults to "score" which displays the numerator and denominator of the score (or just the numerator if no max is provided).
    "color": "#ff0000", // optional, colour of the score display, (defaults to red for "error", dark grey for "pending", and green for "success")
  "text": {
    "value": "Tests Failed", // text status to display
    "color": "#404040", // optional, colour of the text, defaults to score display
  "link": {
    "text": "Click to view report",
    "url": "https://www.example.com"
  "feedback": [{
    "type": "iframe", // optional, defaults to "iframe", can also be "image", "text", "audio", or "video"
    "title": "Results",
    "url": "https://www.example.com", // present if type == "iframe"
    "text": "Feedback text", // present if type == "text",
    "caption": "Caption Text" // present if type == "image"
  "visibility": "class", // optional, can also be "author", or "staff",
  "thumbnail": "https://www.example.com/thumbnail.png"


Completion Tracking

Under the "Completion Settings" tab of the widget on which the webhook integration is added, additional completion criteria can be set up to mark the activity block as completed once the webhook has responded with a "success" status.



Content aside

  • 1 yr agoLast active
  • 91Views
  • 2 Following