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:

  1. Obtain student platform IDs—you'll use these as the actor in all events:
    • Option 1 (Recommended): Implement Level 2 (LTI) and store the sub field from LTI tokens
    • Option 2 (Without LTI): Look up platform IDs by email using the roster API (see Alternative: Roster Lookup below)
  2. Request OAuth credentials with the events.write scope (see Authentication Guide)

Progressive Implementation

Implement Caliper events in phases to balance integration effort with analytics value:

Phase 1: Core Question Events (highest value)

  1. Questions Started (when question displays)
  2. Questions Answered (when student submits)
  3. 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: Always http://purl.imsglobal.org/ctx/caliper/v1p2
  • id: Unique UUID for this event
  • type: Event type (e.g., AssessmentItemEvent, GradeEvent)
  • actor: Student's platform ID (the sub from LTI token, formatted as urn:uuid:{sub})
  • action: What happened (e.g., Started, Completed, Graded)
  • object: What the action was performed on
  • eventTime: ISO 8601 timestamp when event occurred
  • edApp: Your app's identifier
  • session: Use urn:tag:auto-attach for 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),
});

Complete event schemas, field requirements, and examples for all supported event types.

Obtain OAuth client credentials and access tokens required for sending Caliper events.

Programmatically create and manage students in TimeBack's roster.

Implement LTI first to get student platform IDs, which you'll use as the actor in all Caliper events.