Get Learner Progress
Retrieve a learner’s progress and scores for a specific lesson. Two endpoints are available depending on your integration type: Embed (for embedded lessons) and LTI (for LTI-launched lessons).
Endpoints
GET /api/public/lessons/:lessonId/progress/:learnerId
GET /api/public/lessons/:lessonId/lti-progress/:ltiUserId?platformId=...&contextId=...Authentication
Both endpoints require authentication using a Bearer token. See Authentication for complete details on API token format, usage, and error handling.
Embed Progress
Retrieve progress for a learner identified by the learnerId used when generating the embed token.
Endpoint
GET /api/public/lessons/:lessonId/progress/:learnerIdPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lessonId | string (UUID) | Yes | The lesson’s unique identifier |
learnerId | string | Yes | The learner ID used in the embed token |
Response
Success Response (200 OK)
{
"lessonId": "550e8400-e29b-41d4-a716-446655440000",
"learnerId": "user-123",
"status": "completed",
"score": 3,
"maxScore": 3,
"currentSectionIndex": 0,
"currentStepIndex": 3,
"totalSteps": 4,
"progressData": {},
"variableState": {},
"items": [],
"userAttributes": {},
"startedAt": "2025-06-01T10:00:00Z",
"completedAt": "2025-06-01T10:15:00Z",
"lastActivityAt": "2025-06-01T10:15:00Z"
}Response Fields
| Field | Type | Description |
|---|---|---|
lessonId | string (UUID) | Lesson identifier |
learnerId | string | Learner identifier |
status | string | Progress status: "not_started", "in_progress", or "completed" |
score | number | null | Current score |
maxScore | number | null | Maximum possible score |
currentSectionIndex | number | Zero-based index of the current section |
currentStepIndex | number | Zero-based index of the current step within the section |
totalSteps | number | null | Total number of steps in the lesson |
progressData | object | null | Full session state for resume (JSONB) |
variableState | object | null | Current variable values (JSONB) |
items | array | null | Per-widget scored results (JSONB) |
userAttributes | object | null | User attributes from the embed token context (JSONB) |
startedAt | string | null | ISO 8601 timestamp when the learner started |
completedAt | string | null | ISO 8601 timestamp when the learner completed |
lastActivityAt | string | ISO 8601 timestamp of the most recent activity |
Example Request
curl -X GET 'https://your-domain.com/api/public/lessons/550e8400-e29b-41d4-a716-446655440000/progress/user-123' \
-H 'Authorization: Bearer tapub_xxxxx.tasec_xxxxx'LTI Progress
Retrieve progress for an LTI user identified by their LTI user ID and platform.
Endpoint
GET /api/public/lessons/:lessonId/lti-progress/:ltiUserIdPath Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lessonId | string (UUID) | Yes | The lesson’s unique identifier |
ltiUserId | string | Yes | The LTI user ID from the LTI token |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
platformId | string | Yes | The LTI platform ID (ltijs platform identifier) |
contextId | string | No | The LTI context (course) ID. Omit to match any context. |
Response
Success Response (200 OK)
{
"lessonId": "550e8400-e29b-41d4-a716-446655440000",
"ltiUserId": "lti-user-456",
"platformId": "platform-789",
"contextId": "course-101",
"courseId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"status": "completed",
"score": 85.0,
"maxScore": 100.0,
"currentSectionIndex": 0,
"currentStepIndex": 3,
"progressData": {},
"variableState": {},
"startedAt": "2025-06-01T10:00:00Z",
"completedAt": "2025-06-01T10:15:00Z",
"lastActivityAt": "2025-06-01T10:15:00Z"
}Response Fields
| Field | Type | Description |
|---|---|---|
lessonId | string (UUID) | Lesson identifier |
ltiUserId | string | LTI user identifier |
platformId | string | LTI platform identifier |
contextId | string | null | LTI context (course) identifier |
courseId | string (UUID) | Internal course identifier |
status | string | Progress status: "not_started", "in_progress", or "completed" |
score | number | null | Current score (0-100) |
maxScore | number | null | Maximum possible score (0-100) |
currentSectionIndex | number | Zero-based index of the current section |
currentStepIndex | number | Zero-based index of the current step within the section |
progressData | object | null | Full session state for resume (JSONB) |
variableState | object | null | Current variable values (JSONB) |
startedAt | string | null | ISO 8601 timestamp when the learner started |
completedAt | string | null | ISO 8601 timestamp when the learner completed |
lastActivityAt | string | ISO 8601 timestamp of the most recent activity |
Example Requests
With Context ID
curl -X GET 'https://your-domain.com/api/public/lessons/550e8400.../lti-progress/lti-user-456?platformId=platform-789&contextId=course-101' \
-H 'Authorization: Bearer tapub_xxxxx.tasec_xxxxx'Without Context ID
curl -X GET 'https://your-domain.com/api/public/lessons/550e8400.../lti-progress/lti-user-456?platformId=platform-789' \
-H 'Authorization: Bearer tapub_xxxxx.tasec_xxxxx'Error Responses
Both endpoints share the same error response format.
401 Unauthorized
Authentication failed. See Authentication Errors for detailed information.
404 Not Found
The lesson, platform, or progress record was not found.
{
"error": "No progress found for this learner and lesson"
}Possible causes:
- The lesson ID does not exist or does not belong to your organization
- The learner/LTI user has not started the lesson yet
- (LTI only) The platform ID does not belong to your organization
422 Unprocessable Entity
The request parameters are invalid.
{
"error": "Invalid lesson ID format"
}500 Internal Server Error
An unexpected error occurred on the server.
{
"error": "Failed to fetch progress data"
}Notes
- Only progress for lessons belonging to your organization can be retrieved
- JSONB fields (
progressData,variableState,items,userAttributes) are returned as-is and will benullwhen not set - The
statusfield can be"not_started","in_progress", or"completed" - For the LTI endpoint, omitting
contextIdreturns the first matching record regardless of context - The embed endpoint’s
itemsfield contains per-widget scored results, useful for detailed analytics