Skip to content
Lou Wolford edited this page Jun 3, 2016 · 14 revisions

ADL LRS Webhooks

Traditionally every xAPI client has to ask the LRS for a specific set of statements to report on. With our webhooks, loosely based from GitHub webhooks, users can create statement filters that filter all incoming statements from that user and pushes them to the user-given client endpoint.

By default webhooks are not enabled, if you wish to use them you need to set the settings config USE_HOOKS to True

API

Registering

Client Request to LRS

POST /hooks
Content-Type: "application/json"
Authorization: "Basic yaddayadda="

{
	“name”: “foo hook request”,
	“config”: {
	    “endpoint”: “http://client/endpoint”,
	    “content-type”: “json”, (either "json" or "form")
	    “secret”: “secret-key”, (this is optional)
        },
	“filters”:{
            “actor”: [{agent object}, {agent object}],
            “verb”: [{verb object}, {verb object}],
            “object”: [{statement_object object}, {statement_object object}],
            “related: [{activity object}, {agent object}]	
        }
}
  • name - The name of your webhook
  • endpoint - Address of your client that will accept statements pushed from the LRS
  • content-type - The LRS will deliver the json payload directly in the body of the POST if value is 'json', else if it is 'form' the body will have 'payload' as a single form parameter and the json as its value. Defaults to 'json' if none give
  • secret - An optional string value. If given a secret key, when returning statements the LRS will set a X-LRS-Signature header value with the HMAC hex digest of the body, using this secret config option as the key
  • filters - See below

LRS Response Back to Client

Status: 201 Created
Location: https://adlnet.gov/hooks/{hook id}

{
	“id”: :id,
	“url”: “https://lrs.adlnet.gov/hooks/:id”,
	“name”: “foo hook request”,
	“config”: {
	    “endpoint”: “http://client/endpoint”,
	    “content-type”: “json”,
	    “secret”: “secret-key”, (if given previously)
        },
	“filters”:{
            “actor”: [{agent object}, {agent object}],
            “verb”: [{verb object}, {verb object}],
            “object”: [{statement_object object}, {statement_object object}],
            “related: [{activity object}, {agent object}]	
        },
	“created_at”: iso date/time,
	“updated_at”: iso date/time
}

The response from the LRS contains the same hook data the user sent, plus the created_at, updated_at, url, and id fields.

Returning Data

LRS Request to Registered Clients

POST client/endpoint (client provided config['endpoint'])
X-LRS-Signature: "hash" (if hook had a secret-key)
Content-Type: "application/json" (client provided config['content_type'])

{
    “id”: :id,
    "statements": [{statement}, {statement}, ...]
}

Retrieve Hook(s)

Returns all of your registered webhooks

GET /hooks
Authorization: "Basic yaddayadda="

(LRS Returns)
201
[{hook object}, {hook object}, ...]

Single hook

Returns the requested hook by id

GET /hooks/:id
Authorization: "Basic yaddayadda="

(LRS Returns)
201
{hook object}

Delete Hook

DELETE /hooks/:id
Authorization: "Basic yaddayadda="

(LRS Returns)
204
' '

Filtering

The webhook filtering works differently than the xAPI querying API in the spec. There are four main fields: actor, verb, object, and related. The first three are each arrays containing objects of that field and the related field is an array not only containing actor/object objects but also special and/or objects. Here is a breakdown of the syntax rules:

  1. The objects in the arrays are OR'd together

  2. Property queries (actor, verb, object, related) are AND'd together once everything in each array is OR'd

  3. Actor, verb, and object properties limit the query to only the specified field

  4. Related field behavior is like the behavior described in the xAPI spec for related_actor and related_activity

  5. Objects in the related property can be AND'd together, instead of OR'd, using an object with a reserved 'and' property and the value being an array of objects to AND together

  6. Related fields can also contain special 'or' objects (like the reserved 'and' objects). These are usually nested inside of 'and' objects

Filter Examples

“filters”:{
    “actor”: [{agent object (bob)}],
}

**Faux SQL**
SELECT statements WHERE actor == agent object

**Sentence Equivalent**
Give me all the statements whose actor is bob.
"filters":{
    "actor": [{agent object 1 (bob)}, {agent object 2 (pete)}],
}
**Faux SQL**
SELECT statements WHERE actor == agent object 1 OR actor == agent object 2

**Sentence Equivalent**
Give me all of the statements whose actor is either bob or pete.
"filters":{
    "actor": [{agent object 1 (bob)}, {agent object 2 (pete)}],
    "verb": [{verb object 1 (skipped)}, {verb object 2 (ran)}],
}
**Faux SQL**
SELECT statements WHERE (actor == agent object 1 OR actor == agent object 2) AND (verb == verb object 1 OR verb == verb object 2)

**Sentence equivalent**
Give me all the statements whose actor either is bob or pete and whose verb is either skipped or ran.
"filters":{
    "verb": [{verb object 1 (passed)}, {verb object 2 (missed)}],
    "object": [{object 1 (question 1)}]
    "related": [{agent object 1 (bob)}, {"and": [{activity object 2 (course 1)}, {activity object 3 (test 2)}]}]
}
**Faux SQL**
SELECT statements WHERE (verb == verb object 1 OR verb == verb object 2) AND (object == object 1) AND ((activity object 2 IN context activities OR activity object 2 IN substatement context activities OR object == activity object 2 OR substatement object == activity object 2) OR (activity object 3 IN context activities OR activity object 3 IN substatement context activities OR object == activity object 3 OR substatement object == activity object 3))

**Sentence equivalent**
Give me all of the statements where students passed or missed question 1 and whose instructor is bob or where the course was course 1 and the test was test 2.
"filters":{
    "related":  [{"and": [{activity object 1 (test 1)}, {"or":[{activity object 2 (course 1)}, {activity object 3 (course 2)}]}]}]

}
**Faux SQL**
SELECT statements WHERE (activity object 1 IN context activities OR activity object 1 IN substatement context activities OR object == activity object 1 OR substatement object == activity object1) AND ((activity object 2 IN context activities OR activity object 2 IN substatement context activities OR object == activity object 2 OR substatement object == activity object 2) OR ((activity object 3 IN context activities OR activity object 3 IN substatement context activities OR object == activity object 3 OR substatement object == activity object 3)))

**Sentence Equivalent**
Give me all the statements about test 1 in courses course 1 and course 2.