Level 3: Caliper Events
Send structured learning activity events to unlock coaching insights and unified analytics across TimeBack's ecosystem.
What Caliper Provides
Caliper Analytics is a 1EdTech standard that defines a structured vocabulary for learning events. By sending Caliper events to TimeBack, you enable:
- Richer coaching insights based on student behavior patterns
- Unified progress tracking across multiple learning apps
- Cross-app intelligence (detecting patterns like assessment avoidance, topic shopping)
- Detailed analytics for educators and administrators
Without Caliper events, TimeBack can only track session time and screen activity. With Caliper, TimeBack understands what students are actually doing—which questions they answer, what they master, when they skip content.
Prerequisites
Before implementing Caliper:
- Obtain student platform IDs—you'll use these as the
actorin all events:- Option 1 (Recommended): Implement Level 2 (LTI) and store the
subfield from LTI tokens - Option 2 (Without LTI): Look up platform IDs by email using the roster API (see Alternative: Roster Lookup below)
- Option 1 (Recommended): Implement Level 2 (LTI) and store the
- Request OAuth credentials with the
events.writescope (see Authentication Guide)
Progressive Implementation
Implement Caliper events in phases to balance integration effort with analytics value:
Phase 1: Core Question Events (highest value)
- Questions Started (when question displays)
- Questions Answered (when student submits)
- Questions Graded (when feedback provided)
These three events power the most valuable coaching insights—accuracy tracking, struggling topic detection, skip pattern analysis.
Phase 2: Progress Tracking 4. XP Awarded (when student earns experience points) 5. Mastery Achieved (when student completes curriculum objectives)
These enable unified progress dashboards and cross-app analytics.
Phase 3: Additional Context (optional) 6. Curriculum content events (AssignableEvent, ViewEvent) 7. Assessment grouping events (AssessmentEvent)
These provide richer context but aren't required for core coaching functionality.
Start with Phase 1. Add Phase 2 when ready for progress reporting. Phase 3 is optional—add only if your app has explicit lessons or assessments that benefit from structured tracking.
Event Types Overview
TimeBack uses four primary event types:
| Event Type | When to Send | What It Powers |
|---|---|---|
| Questions Started | When a question is displayed to the student | Detects question skip patterns, measures question engagement time |
| Questions Answered | When a student submits an answer | Tracks accuracy, identifies struggling topics, detects rapid guessing |
| XP Awarded | When a student earns experience points | Progress tracking, engagement metrics, cross-app XP leaderboards |
| Mastery Achieved | When a student completes curriculum objectives | Completion tracking, mastery dashboards, prerequisite unlocking |
Start with questions and answers—these power the most valuable coaching insights. Add XP and mastery when ready.
For complete event schemas and field documentation, see Caliper Events Reference.
How to Send Events
All Caliper events go to a single endpoint:
POST https://platform.timeback.com/events/1.0/
Include your OAuth access token (see Authentication Guide):
await fetch('https://platform.timeback.com/events/1.0/', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(event),
});
Send events as bare JSON—one event per POST request:
{
"@context": "http://purl.imsglobal.org/ctx/caliper/v1p2",
"id": "urn:uuid:event-unique-id",
"type": "AssessmentItemEvent",
"actor": "urn:uuid:student-platform-id",
"action": "Started",
"object": {
"id": "urn:uuid:question-id",
"type": "AssessmentItem",
"name": "7 × 8 = ?"
},
"eventTime": "2025-12-15T10:30:00.000Z",
"edApp": "urn:uuid:your-app-id",
"session": "urn:tag:auto-attach"
}
Required fields (see Caliper Events Reference for complete documentation):
@context: Alwayshttp://purl.imsglobal.org/ctx/caliper/v1p2id: Unique UUID for this eventtype: Event type (e.g.,AssessmentItemEvent,GradeEvent)actor: Student's platform ID (thesubfrom LTI token, formatted asurn:uuid:{sub})action: What happened (e.g.,Started,Completed,Graded)object: What the action was performed oneventTime: ISO 8601 timestamp when event occurrededApp: Your app's identifiersession: Useurn:tag:auto-attachfor automatic session attribution
Sending Pattern
Send events as they happen in real-time. For production reliability, use a queue (Redis, SQS, RabbitMQ) to decouple event sending from user-facing operations and guarantee delivery.
Implementation
Request the Caliper scope when registering or email the TimeBack team:
scope: https://purl.imsglobal.org/spec/caliper/v1p2/scope/events.write
Fire events when student actions occur:
// When question appears
await fetch('https://platform.timeback.com/events/1.0/', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
'@context': 'http://purl.imsglobal.org/ctx/caliper/v1p2',
id: `urn:uuid:${crypto.randomUUID()}`,
type: 'AssessmentItemEvent',
actor: `urn:uuid:${user.platformId}`, // From LTI 'sub'
action: 'Started',
object: {
id: `urn:uuid:${question.id}`,
type: 'AssessmentItem',
name: question.text,
},
eventTime: new Date().toISOString(),
edApp: 'urn:uuid:yourapp',
session: 'urn:tag:auto-attach',
}),
});
Success responses return 200 OK with empty body.
Alternative: Roster Lookup
If your app accepts students launching outside TimeBack App (direct browser access), you won't have LTI tokens to get platform IDs. You can look up platform IDs by email using the roster API.
Use case: Students who access your app directly (not launched from TimeBack App) but you still want to send their learning events to TimeBack.
Request Roster Scope
Request the roster read scope along with events write scope:
scope: https://purl.imsglobal.org/spec/or/v1p2/scope/roster.readonly
scope: https://purl.imsglobal.org/spec/caliper/v1p2/scope/events.write
Look Up Platform ID by Email
async function getPlatformId(email: string, accessToken: string): Promise<string | null> {
const filter = encodeURIComponent(`email='${email}'`);
const url = `https://platform.timeback.com/rostering/1.0/users?filter=${filter}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
});
if (!response.ok) {
return null;
}
const data = await response.json();
if (data.users.length === 0) {
return null; // User not in TimeBack system
}
return data.users[0].sourcedId; // This is the platform ID
}
Important: Only students who exist in TimeBack's roster will have platform IDs. If lookup returns null, the student isn't in TimeBack's system—don't send Caliper events for them.
Common Pitfalls
Not using platform ID as actor
// ❌ Bad: Using your internal user ID
actor: `urn:uuid:${user.id}`;
// ✅ Good: Using TimeBack platform ID
actor: `urn:uuid:${user.platformId}`; // From LTI 'sub' or roster lookup
Sending events without authentication
// ❌ Bad: No auth token
await fetch(url, { body: JSON.stringify(event) });
// ✅ Good: Include OAuth token
await fetch(url, {
headers: { Authorization: `Bearer ${accessToken}` },
body: JSON.stringify(event),
});
Related Docs
Caliper Events Reference
Complete event schemas, field requirements, and examples for all supported event types.
Authentication
Obtain OAuth client credentials and access tokens required for sending Caliper events.
Level 1: Student Onboarding
Programmatically create and manage students in TimeBack's roster.
Level 2: LTI Launch
Implement LTI first to get student platform IDs, which you'll use as the actor in all Caliper events.