Tracking Progress
Track student activities and calculate XP
Overview
Track student activities and calculate progress in your learning application.
You'll use Caliper to send activity events and OneRoster to store results in the gradebook.
This data powers dashboards, reports, and adaptive learning features.
Choose Environment
Decide on Staging for development or Production for live apps.
Authenticate
Get an access token using your Timeback credentials (see Authentication).
Send ActivityEvents
Use Caliper to track when students start and complete activities.
Record Results
Use OneRoster to store scores, XP, and mastery data.
Using Playcademy?
Activity tracking is automatic via startActivity() and endActivity().
Environments
Find the Caliper API base URL for your target environment:
| Environment | Base URL |
|---|---|
| Staging | https://caliper-staging.alpha-1edtech.ai |
| Production | https://caliper.alpha-1edtech.ai |
Send Activity Events
Timeback uses a custom Caliper profile with two event types:
ActivityEvent
Record when a student completes an activity with accuracy, XP, and mastery data.
The generated.items array can include:
| Type | Description |
|---|---|
totalQuestions | The total number of questions presented in a graded activity |
correctQuestions | The number of questions answered correctly in a graded activity |
xpEarned | Awarded Timeback XP points |
masteredUnits | Number of learning units mastered (typically 1 when a student completes a unit above accuracy/time thresholds) |
curl -X POST $TIMEBACK_CALIPER_URL/ims/caliper/v1p2/events \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "sensor": "https://your-app.com", "sendTime": "2025-11-18T10:15:00Z", "dataVersion": "http://purl.imsglobal.org/ctx/caliper/v1p2", "data": [{ "@context": "http://purl.imsglobal.org/ctx/caliper/v1p2", "id": "urn:uuid:c51570e4-f8ed-4c18-bb3a-dfe51b2cc594", "type": "ActivityEvent", "profile": "TimebackProfile", "eventTime": "2025-11-18T10:15:00Z", "action": "Completed", "actor": { "id": "https://api.alpha-1edtech.ai/ims/oneroster/rostering/v1p2/users/student-123", "type": "TimebackUser", "email": "student@example.com" }, "object": { "id": "fractions-quiz", "type": "TimebackActivityContext", "subject": "Math", "app": { "name": "Math App" }, "activity": { "id": "fractions-quiz", "name": "Fractions Quiz" }, "course": { "id": "https://api.alpha-1edtech.ai/ims/oneroster/rostering/v1p2/courses/math-grade-5", "name": "Math Grade 5" } }, "generated": { "id": "metrics-123", "type": "TimebackActivityMetricsCollection", "attempt": 1, "items": [ { "type": "totalQuestions", "value": 10 }, { "type": "correctQuestions", "value": 8 }, { "type": "xpEarned", "value": 100 }, { "type": "masteredUnits", "value": 1 } ] } }] }'const event = { '@context': 'http://purl.imsglobal.org/ctx/caliper/v1p2', id: `urn:uuid:${crypto.randomUUID()}`, type: 'ActivityEvent', profile: 'TimebackProfile', eventTime: new Date().toISOString(), action: 'Completed', actor: { id: `${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/users/student-123`, type: 'TimebackUser', email: 'student@example.com', }, object: { id: 'fractions-quiz', type: 'TimebackActivityContext', subject: 'Math', app: { name: 'Math App' }, activity: { id: 'fractions-quiz', name: 'Fractions Quiz' }, course: { id: `${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/courses/math-grade-5`, name: 'Math Grade 5', }, }, generated: { id: 'metrics-123', type: 'TimebackActivityMetricsCollection', attempt: 1, items: [ { type: 'totalQuestions', value: 10 }, { type: 'correctQuestions', value: 8 }, { type: 'xpEarned', value: 100 }, { type: 'masteredUnits', value: 1 }, ], },}await fetch(`${TIMEBACK_CALIPER_URL}/ims/caliper/v1p2/events`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ sensor: 'https://your-app.com', sendTime: new Date().toISOString(), dataVersion: 'http://purl.imsglobal.org/ctx/caliper/v1p2', data: [event], }),})TimeSpentEvent
Record how much time a student spent learning:
curl -X POST $TIMEBACK_CALIPER_URL/ims/caliper/v1p2/events \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "sensor": "https://your-app.com", "sendTime": "2025-11-18T10:15:00Z", "dataVersion": "http://purl.imsglobal.org/ctx/caliper/v1p2", "data": [{ "@context": "http://purl.imsglobal.org/ctx/caliper/v1p2", "id": "urn:uuid:a1b2c3d4-e5f6-7890-abcd-ef1234567890", "type": "TimeSpentEvent", "profile": "TimebackProfile", "eventTime": "2025-11-18T10:15:00Z", "action": "SpentTime", "actor": { "id": "https://api.alpha-1edtech.ai/ims/oneroster/rostering/v1p2/users/student-123", "type": "TimebackUser", "email": "student@example.com" }, "object": { "id": "fractions-quiz", "type": "TimebackActivityContext", "subject": "Math", "app": { "name": "Math App" }, "course": { "id": "https://api.alpha-1edtech.ai/ims/oneroster/rostering/v1p2/courses/math-grade-5", "name": "Math Grade 5" } }, "generated": { "id": "time-metrics-123", "type": "TimebackTimeSpentMetricsCollection", "items": [ { "type": "active", "value": 240 }, { "type": "inactive", "value": 60 } ] } }] }'const event = { '@context': 'http://purl.imsglobal.org/ctx/caliper/v1p2', id: `urn:uuid:${crypto.randomUUID()}`, type: 'TimeSpentEvent', profile: 'TimebackProfile', eventTime: new Date().toISOString(), action: 'SpentTime', actor: { id: `${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/users/student-123`, type: 'TimebackUser', email: 'student@example.com', }, object: { id: 'fractions-quiz', type: 'TimebackActivityContext', subject: 'Math', app: { name: 'Math App' }, course: { id: `${TIMEBACK_API_URL}/ims/oneroster/rostering/v1p2/courses/math-grade-5`, name: 'Math Grade 5', }, }, generated: { id: 'time-metrics-123', type: 'TimebackTimeSpentMetricsCollection', items: [ { type: 'active', value: 240 }, { type: 'inactive', value: 60 }, ], },}await fetch(`${TIMEBACK_CALIPER_URL}/ims/caliper/v1p2/events`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ sensor: 'https://your-app.com', sendTime: new Date().toISOString(), dataVersion: 'http://purl.imsglobal.org/ctx/caliper/v1p2', data: [event], }),})Record Results with XP
Store student results with XP, accuracy, and mastery data using OneRoster.
Create AssessmentLineItem
Define what's being graded (e.g., a quiz or activity).
curl -X POST $TIMEBACK_API_URL/ims/oneroster/gradebook/v1p2/assessmentLineItems \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "assessmentLineItem": { "status": "active", "title": "Fractions Quiz", "componentResource": { "sourcedId": "fractions-quiz-resource" } } }'const lineItem = { status: 'active', title: 'Fractions Quiz', componentResource: { sourcedId: 'fractions-quiz-resource', },}await fetch(`${TIMEBACK_API_URL}/ims/oneroster/gradebook/v1p2/assessmentLineItems`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ assessmentLineItem: lineItem }),})Create AssessmentResult
Store the student's score, XP, accuracy, and mastery progress.
The metadata field can include custom data like xp, accuracy, and masteredUnits.
curl -X POST $TIMEBACK_API_URL/ims/oneroster/gradebook/v1p2/assessmentResults \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "assessmentResult": { "status": "active", "assessmentLineItem": { "sourcedId": "fractions-quiz-line-item" }, "student": { "sourcedId": "student-123" }, "score": 85, "scoreStatus": "fully graded", "scoreDate": "2025-11-18T10:15:00Z", "metadata": { "xp": 100, "accuracy": 85, "totalQuestions": 10, "correctQuestions": 8.5, "masteredUnits": 1 } } }'const result = { status: 'active', assessmentLineItem: { sourcedId: 'fractions-quiz-line-item', }, student: { sourcedId: 'student-123', }, score: 85, scoreStatus: 'fully graded', scoreDate: new Date().toISOString(), metadata: { xp: 100, accuracy: 85, totalQuestions: 10, correctQuestions: 8.5, masteredUnits: 1, },}await fetch(`${TIMEBACK_API_URL}/ims/oneroster/gradebook/v1p2/assessmentResults`, { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ assessmentResult: result }),})XP Calculation
1 XP = 1 minute of active learning time. See Activities & XP for the full breakdown.
XP is awarded based on accuracy and attempt number. The 80% accuracy threshold ensures students have demonstrated mastery before earning XP.
First attempt:
| Accuracy | Multiplier | Description |
|---|---|---|
| 100% | 1.25x | Bonus for perfect accuracy |
| 80-99% | 1.0x | Full XP for mastery |
| < 80% | 0x | No XP (mastery not demonstrated) |
Re-attempts (diminishing returns to encourage focused first attempts):
| Attempt | Multiplier |
|---|---|
| 1st re-attempt | 0.5x |
| 2nd re-attempt | 0.25x |
| 3rd+ re-attempts | 0x |
