Overview
- Overview
- 1. Authentication
- 2. Responses
- 3. Validation errors
- 4. Event processing
- 5. General guidelines
This document is a Caliper sensor implementation guide for developers integrating with the Unizin Data Platform. It defines the validation performed by the Caliper endpoint, the endpoint's responses, and how to design payloads that make the most of the UDP's capabilities.
The Unizin Data Platform (UDP) ingests Caliper event streams through a Caliper endpoint exposed over the web (HTTPS only). For each Caliper envelope it ingests, the Caliper endpoint performs two major operations:
- Validates the HTTP request, Caliper envelope, and Caliper event(s)
- Routes events for processing before being persisted in the UDP Event store.
The Endpoint's HTTP response will vary based on the validation and routing it performs.
1. Message authentication
Caliper events posted to your Caliper endpoint MUST be authenticated with a token granted by Unizin. If a Caliper event envelope or Caliper event is posted without a valid authentication token, it is rejected by the Caliper endpoint.
Per the Caliper 1.1 specification, a tool's Caliper sensor implementation:
SHOULD ... set the Authorization request header field using the "Bearer" authentication scheme described in RFC 6750, Section 2.1. The b64token authorization credential sent by a Sensor MUST be one the Endpoint can validate although the credential MAY be opaque to the emitting Sensor itself.
Your Caliper endpoint will inspect the Authorization:
request header for a Bearer token and compare it agains a list of valid tokens.
An example header for a Caliper message sent over HTTPS would therefore look like this:
POST /caliper-endpoint HTTP/1.1 Host: server.example.com Authorization: Bearer [some_granted_token]
1.1 Granting and revoking auth tokens
At present, Unizin's technical services team will grant and revoke authentication tokens on Institution's behalf. Tokens are granted on a per-tool basis. It is strongly recommended that institutions do not share the same token among multiple tool providers. If the same auth token is granted to multiple tool providers, then all are subject to the validity of a token that may need to revoked if a single tool provider were to abuse a token.
2. Responses
In a prod
environment, the Caliper's endpoint responses are terse to keep the endpoint performant at scale. We call these "common" responses (see below).
In a sit
environment, the Caliper endpoint's responses are verbose (see below). The responses are intended to aid in debugging your Caliper event stream integration. If a valid HTTP request, the Endpoint's response will contain information about your envelope and event conformance with Caliper along with information describing how events were routed for processing.
Response HTTP status codes
The endpoint may return different status codes depending on the results of validation.
HTTP request errors:
401
- Unauthorized415
- Unsupported Media Type - JSON payload missing or malformed.
Caliper conformance errors:
400
- Non-conformant envelope, or all events non-conformant (distinct from202
below)422
- Non-conformant envelopedataVersion
. NOTE: A baddataVersion
will always cause a422
status, even when the Endpont is run in asit
environment and other validation errors are returned.
Success:
200
- Success! Valid HTTP request, conformant envelope, all events conformant202
- Partial Success. Valid request, conformant envelope, but at least one conformant event amoung other non-conformant events.
Response body
For any given request, the Caliper endpoint will respond in one of two styles.
Common response
In a prod
environment, the Caliper endpoint will always and only return a common response. In a sit
environment, a common response is given if and only if there is a validation error on the HTTP request itself (e.g., an invalid authentication token is used). In such cases, the Caliper endpoint rejects the request without inspecting the Caliper enevelope or its event(s).
{ "error": "Unauthorized", "message": "Bearer token missing or not recognized" }
Verbose response
In a sit
environment, the Caliper endpoint will always return a verbose response if the HTTP request is valid.
A verbose response is divided into two sections.
An accepted_events
attribute contains information about all of the conformant events that were accepted and to which processing they were routed (these are called "topics"). An errors
attribute contains information about the Caliper envelope and all of the events that did not conform with Caliper.
{ 'accepted_events': [ { 'id': 'urn:uuid:b46f370c-79e0-433f-9f2b-2d750155e338', 'topics': { '': ' ', ... } }, ... ] 'errors': { 'envelope': [ ], 'events': [ { 'id': 'urn:uuid:b46f370c-79e0-433f-9f2b-2d750155e337', 'index': 0, 'errors': ['Event `actor` attribute must an object or ' 'string.'], }, ... ] } }
3. Validation errors: requests, envelopes, events
The UDP Caliper endpoint only accepts valid HTTP requests with content-type
of JSON.
HTTP requests
Requirement | Error message |
---|---|
Authentication token is present and valid |
Bearer token missing or not recognized
|
Content type is JSON |
Unsupported Media Type", "message": "application/json payload expected.
|
Caliper envelope
All events posted to the Endpoint must be delivered in a Caliper envelope. Caliper envelopes must conform to the version 1.1 of the IMS Global Caliper standard. The following validation is performed on Caliper envelopes.
Requirement | Error message |
---|---|
sensor is present |
Event envelope must include a `sensor` attribute
|
sendTime is present and in ISO 8601 format |
Event envelope `sendTime` attribute must be an ISO 8601 time string formated like "yyyy-mm-ddThh:mm:ss.SSSZ".
|
dataVersion is present |
Event envelope `dataVersion` attribute must be a version like "http://purl.imsglobal.org/ctx/caliper/v1p1"
|
dataVersion is valid |
Event envelope `data` attribute must be an array with at least one element.
|
Caliper events
All events in a Caliper envelope must conform with the Caliper standard. The Caliper endpoint will reject any events that fail the following requirements.
Requirement | Error message |
---|---|
id is present |
Event `id` must be present. Version 4 UUID is recommended.
|
@context is present and valid |
Event `@context` must be a version like "http://purl.imsglobal.org/ctx/caliper/v1p1".
|
actor is present |
Event `actor` attribute must an object or string.
Note: we recommend defining actor as a hash with an id and type attribute.
Alternatively, actor may be defined as a string.
|
action is presenttype is present
|
"Event `type` and `action` must be present, and `action` must be valid for `type`.
|
eventTime is present and valid ISO 8601 format |
Event `eventTime` attribute must be an ISO 8601 time string formated like "yyyy-mm-ddThh:mm:ss.SSSZ".
|
4. Event processing
When Caliper events are accepted, the response includes information describing to which kind of processing the event was routed.
At present, two types of processing are supported:
- Event record processing (e.g., Caliper validation, UCDM enrichment)
- Latency reduction processing (e.g., updating value in the object store)
Event record processing is applied to all events captured by the UDP’s Caliper endpoint. Event record processing entails taking a valid Caliper event and persisting it in the Event Store. Unizin defines two tiers of Event record processing.
- Silver tier processing: records are persisted as-is into the UDP Event store.
- Gold tier processing: records are commonly-modeled and enriched with data before persistence in the UDP Event store
(See further documentation on the UDP Caliper endpoint's event processing.)
5. General guidelines
Make your event payloads consistent
In practice, the UDP endpoint examines the attributes in event payloads to determine if they qualify for processing beyond standard processing. The UDP endpoint then routes an event to all of the kinds of processing for which it qualifies (our processing types are categorized into two main tiers).
To enable event processing beyond Silver tier event record processing, Unizin will build custom integrations for events streamed by your tool. To make our development efficient, we strongly urge you to:
- Provide a standard
edApp
value (so we know how to read the rest of your event payload) - Use the same event shape across all of your events
- Use consistent, predictable patterns for attribute values, particularly identifiers
- Document your event payload shapes and attribute patterns
- Share your documentation with Unizin (this enables us to write event processing based on your event attribute data).
Make your identifiers predictable IRIs or URNs
We suggest you define the identifiers included in your event payloads as Internationalized Resource Identifiers, or IRIs (RFC 3987). The UDP’s common modeling engine will expect identifiers to be IRIs. A known, predictable string pattern will allow for the UDP’s common modeling engine to strip the relevant piece(s) of the id that can cross-reference to existing data in the relational store.
Alternatively, if your identifiers are not normally IRIs, we suggest constructing them as URNs, which are useful for showing the object’s location in the app’s internal hierarchy.
For example:
“edApp.id”: “http://unizin.instructure.com/” “session.id”: “urn:umich:engin:leccap:session:T7Lzgsmtq0x2e1204jut6sop6”
Include LTI launch parameters in your payload
If your tool is launched via LTI, Unizin recommends including the LTI launch parameters passed to your tool via an event’s federatedSession
object. Of particular interest are the LTI parameters representing the LMS course ID and the LMS user ID corresponding to the event. These values are useful in commonly modeling your event data with object data.
In the example below, the LMS course and user IDs are passed via messageParameters
(this is arbitrary) and identified with the attributes lis_course_offering_sourcedid
and lis_person_sourcedid
, respectively.
"federatedSession": { "type": "LtiSession", "id": "urn:session-id-localized/lti/oauth_nonce/5a81e2eb557427.65333446", "messageParameters": { "custom_canvas_course_id": "12345", "custom_canvas_user_id": "98765", "lis_course_offering_sourcedid": "test_99999003", "lis_person_sourcedid": "11235813", "resource_link_id": "a1b2c3d4e5f6g7h8i9j10" }, "user": "https://university.edu/#profile:smith" }