Level 4: Insights API

Access coaching insights generated from student learning activity to power dashboards, reports, and intervention workflows.

What Insights Provides

The Insights API gives you read access to coaching insights that TimeBack generates from Caliper events (Level 3). By integrating with Insights, you enable:

  • Student behavior dashboards showing time-on-task and waste patterns
  • Session-level analytics with detailed insight breakdowns
  • Trend analysis over configurable time ranges
  • Cross-session aggregations for progress tracking

Without the Insights API, you can send learning events but can't programmatically access the insights TimeBack generates. With Insights, you can build custom dashboards and integrate coaching data into your app's existing analytics.

Prerequisites

Before implementing Insights:

  1. Implement Level 3 (Caliper Events)—insights are generated from Caliper events you send
  2. Request OAuth credentials with the events.readonly scope (see Authentication Guide)

API Endpoints

The Insights API provides four endpoints for accessing coaching data:

Endpoint Description
GET /insights/1.0/users/{userId} Get insights for a specific user
GET /insights/1.0/users/{userId}/sessions Get session list for a user
GET /insights/1.0/sessions/{sessionId} Get insights for a specific session
GET /insights/1.0/users/{userId}/overview Get aggregated trend and breakdown data

Authentication

All Insights endpoints require OAuth 2.0 authentication. Request the events read scope:

scope: https://purl.imsglobal.org/spec/caliper/v1p2/scope/events.readonly

Include your access token in requests:

const response = await fetch(`https://platform.timeback.com/insights/1.0/users/${userId}`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
});

Get User Insights

Retrieve insights for a specific user with optional filtering and pagination.

GET /insights/1.0/users/{userId}

Query Parameters

Parameter Type Required Description
applicationId uuid No Filter insights to a specific learning app
after datetime No Filter insights after this timestamp (inclusive)
before datetime No Filter insights before this timestamp (inclusive)
limit integer No Maximum items to return (1-100, default 20)
offset integer No Number of items to skip (default 0)
type string No Comma-separated insight types to filter by

Example Request

const userId = 'student-platform-id'; // From LTI 'sub' or roster lookup
const response = await fetch(
  `https://platform.timeback.com/insights/1.0/users/${userId}?limit=10&after=2025-01-01T00:00:00Z`,
  {
    headers: { Authorization: `Bearer ${accessToken}` },
  },
);

const data = await response.json();

Example Response

{
  "session": {
    "startedAtTime": "2025-01-15T09:00:00Z",
    "endedAtTime": "2025-01-15T10:30:00Z",
    "durationInSeconds": 5400,
    "wasteDurationInSeconds": 720,
    "wastePercentage": 13
  },
  "insights": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "insightType": "Idling",
      "reason": "No activity detected for extended period",
      "startedAtTime": "2025-01-15T09:15:00Z",
      "endedAtTime": "2025-01-15T09:20:00Z",
      "durationInSeconds": 300,
      "version": "v1"
    }
  ],
  "offset": 0,
  "limit": 10,
  "total": 1
}

Get User Sessions

Retrieve sessions for a user with optional filtering.

GET /insights/1.0/users/{userId}/sessions

Query Parameters

Parameter Type Required Description
applicationId uuid No Filter sessions to a specific learning app
startedAfter datetime No Lower bound for session start time (inclusive)
startedBefore datetime No Upper bound for session start time (inclusive)
isProctored boolean No Filter by proctored status
limit integer No Maximum items to return (1-100, default 20)
offset integer No Number of items to skip (default 0)

Example Request

const response = await fetch(
  `https://platform.timeback.com/insights/1.0/users/${userId}/sessions?startedAfter=2025-01-01T00:00:00Z`,
  {
    headers: { Authorization: `Bearer ${accessToken}` },
  },
);

const data = await response.json();

Example Response

{
  "sessions": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "applicationId": "learning-app-uuid",
      "startedAtTime": "2025-01-15T09:00:00Z",
      "endedAtTime": "2025-01-15T10:30:00Z",
      "durationInSeconds": 5400,
      "wasteDurationInSeconds": 720,
      "wastePercentage": 13,
      "isProctored": true,
      "proctoredResult": "PASSED",
      "recordingStartedAtTime": "2025-01-15T09:00:05Z",
      "recordingEndedAtTime": "2025-01-15T10:29:55Z",
      "recordingS3Key": "recordings/2025/01/15/session-550e8400.webm"
    }
  ],
  "offset": 0,
  "limit": 20,
  "total": 1
}

Get Session Insights

Retrieve insights for a specific session.

GET /insights/1.0/sessions/{sessionId}

Path Parameters

Parameter Type Required Description
sessionId uuid Yes Session ID from the sessions list

Query Parameters

Parameter Type Required Description
isProctored boolean No Filter insights by proctored status
limit integer No Maximum items to return (1-100, default 20)
offset integer No Number of items to skip (default 0)
type string No Comma-separated insight types to filter by

Example Request

const sessionId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(`https://platform.timeback.com/insights/1.0/sessions/${sessionId}`, {
  headers: { Authorization: `Bearer ${accessToken}` },
});

const data = await response.json();

Get User Insights Overview

Retrieve aggregated overview data including trends and breakdowns for a time range.

GET /insights/1.0/users/{userId}/overview

Query Parameters

Parameter Type Required Description
startedAfter datetime Yes Lower bound for time window (inclusive)
startedBefore datetime Yes Upper bound for time window (exclusive)
targetTimezone string Yes IANA timezone for local-day bucketing

Example Request

const params = new URLSearchParams({
  startedAfter: '2025-01-01T00:00:00Z',
  startedBefore: '2025-01-08T00:00:00Z',
  targetTimezone: 'America/New_York',
});

const response = await fetch(`https://platform.timeback.com/insights/1.0/users/${userId}/overview?${params}`, {
  headers: { Authorization: `Bearer ${accessToken}` },
});

const data = await response.json();

Example Response

{
  "summary": {
    "totalDurationInSeconds": 36000,
    "totalWasteDurationInSeconds": 5400,
    "wastePercentage": 15,
    "biggestInsight": {
      "level": "OnDeviceDistractions",
      "durationInSeconds": 2400,
      "wastePercentage": 7
    }
  },
  "trend": {
    "buckets": [
      {
        "startedAtTime": "2025-01-01T00:00:00Z",
        "endedAtTime": "2025-01-02T00:00:00Z",
        "totalDurationInSeconds": 7200,
        "wasteDurationInSeconds": 1080,
        "wastePercentage": 15,
        "levels": [
          { "level": "StudentNotPresent", "durationInSeconds": 300 },
          { "level": "OnDeviceDistractions", "durationInSeconds": 780 }
        ]
      }
    ]
  },
  "breakdown": {
    "levels": [
      {
        "level": "OnDeviceDistractions",
        "durationInSeconds": 2400,
        "wastePercentage": 7,
        "subtypes": [
          { "insightType": "Game", "durationInSeconds": 1200 },
          { "insightType": "NonLearningContent", "durationInSeconds": 1200 }
        ]
      }
    ]
  }
}

Insight Types

TimeBack generates the following insight types from student activity:

Waste Insights (Time Off-Task)

Type Description
AwayFromSeat Student not detected at their desk
EyesOffScreen Student looking away from screen
Idling No activity for extended period
NonLearningContent Browsing non-educational content
Socializing Social media or messaging activity
IgnoringHelp Student dismissed or ignored coaching suggestions
SkipAssessment Student skipped assessment questions
AbandonedAssessment Student left assessment incomplete
TopicShopping Rapidly switching between topics without progress

Proctoring Insights

Type Description
UnauthorizedAppUse Using applications not allowed during session
HelpFromAnotherPerson Receiving unauthorized help

Safety Insights

Type Description
BullyingOrHarassment Bullying or harassment detected
EmbarrassingOrDefaming Embarrassing or defaming content
MentalHealthDistress Signs of mental health distress
PornographyOrSexualContent Pornographic or sexual content
SelfHarmOrSuicide Self-harm or suicide-related content
SubstanceAbuse Substance abuse detected
ViolenceOrAbuse Violence or abuse detected
WebcamNudity Nudity detected via webcam

Overview Levels

Overview data groups insights into four levels:

Level Description
StudentNotPresent Student away from seat or eyes off screen
EnvironmentalDistractions External distractions (eating, socializing)
OnDeviceDistractions Digital distractions (games, social media)
LearningAppBestPractices Learning behavior issues (skipping, shopping)

Looking Up Application Information

Insights and sessions include an applicationId field that identifies which learning app the data came from. To map application IDs to application names and details, use the Applications API.

Get All Applications

GET /applications/1.0

This endpoint returns all applications. Each application's sourcedId is the applicationId you'll see in insights responses.

Required scope: https://purl.imsglobal.org/spec/lti/v1p3/scope/lti.readonly

This endpoint supports filtering, pagination, sorting, and field selection. See OneRoster API Conventions for details.

Example Request

const response = await fetch('https://platform.timeback.com/applications/1.0', {
  headers: { Authorization: `Bearer ${accessToken}` },
});

const data = await response.json();

Example Response

{
  "applications": [
    {
      "sourcedId": "app-uuid",
      "name": "Math Learning Suite",
      "description": "Comprehensive math learning platform",
      "logoUrl": "https://example.com/logo.png",
      "applicationType": "learning_app",
      "wasteMeter": "on",
      "proctoringMode": "off"
    }
  ],
  "offset": 0,
  "limit": 10,
  "total": 1
}

Building an Application Lookup Map

Cache application information to efficiently display app names in your dashboards:

interface ApplicationInfo {
  name: string;
  logoUrl: string;
}

async function buildApplicationLookup(accessToken: string): Promise<Map<string, ApplicationInfo>> {
  const response = await fetch('https://platform.timeback.com/applications/1.0?limit=100', {
    headers: { Authorization: `Bearer ${accessToken}` },
  });

  const data = await response.json();
  const applicationMap = new Map<string, ApplicationInfo>();

  for (const app of data.applications) {
    applicationMap.set(app.sourcedId, {
      name: app.name,
      logoUrl: app.logoUrl,
    });
  }

  return applicationMap;
}

// Usage: Display application name for a session
const applicationLookup = await buildApplicationLookup(accessToken);
const session = sessions[0];
const applicationInfo = applicationLookup.get(session.applicationId);
console.log(`Session in: ${applicationInfo?.name}`); // "Session in: Math Learning Suite"

Common Use Cases

Building a Student Dashboard

Use the overview endpoint to show weekly trends:

async function getWeeklyOverview(userId: string, timezone: string): Promise<Overview> {
  const now = new Date();
  const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);

  const params = new URLSearchParams({
    startedAfter: weekAgo.toISOString(),
    startedBefore: now.toISOString(),
    targetTimezone: timezone,
  });

  const response = await fetch(`https://platform.timeback.com/insights/1.0/users/${userId}/overview?${params}`, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });

  return response.json();
}

Listing Recent Sessions with Waste Stats

async function getRecentSessions(userId: string): Promise<Session[]> {
  const response = await fetch(`https://platform.timeback.com/insights/1.0/users/${userId}/sessions?limit=10`, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });

  const data = await response.json();
  return data.sessions;
}

Drilling into Session Details

async function getSessionDetails(sessionId: string): Promise<Insights> {
  const response = await fetch(`https://platform.timeback.com/insights/1.0/sessions/${sessionId}`, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });

  return response.json();
}

Error Handling

The API returns standard HTTP status codes:

Status Description
200 Success
400 Bad request (invalid parameters)
401 Unauthorized (missing or invalid token)
403 Forbidden (insufficient scope)
404 Not found (session or user doesn't exist)
500 Internal server error

Error responses include details:

{
  "error": "Bad request",
  "message": "Invalid UUID format for userId"
}

Insights are generated from Caliper events. Implement Level 3 first to start generating insights.

Obtain OAuth client credentials and access tokens required for the Insights API.

Learn about filtering, pagination, sorting, and field selection for the Applications API.