Academy Statistics
Programmatic access to the academy figures shown in the CMS — onboarding and course completion, journey progress, and quiz performance — plus per-user progress for HR / LMS integrations.
These endpoints share their queries with the in-app academy statistics, so the numbers match what managers see in the CMS. Unlike the CMS there is no signed-in user, so figures cover the whole customer by default; pass group_ids on the aggregate endpoints to narrow them.
Required scope: read:stats
Endpoints
/api/open/v1/stats/academy/onboardingOnboarding completion totals
/api/open/v1/stats/academy/coursesCompletion rates per published course
/api/open/v1/stats/academy/journeysCompletion totals per published journey
/api/open/v1/stats/academy/quizzes/{quiz_id}Per-question quiz performance summary
/api/open/v1/stats/academy/users/{user_id}/coursesA single user's course progress
/api/open/v1/stats/academy/users/{user_id}/onboardingA single user's onboarding status
Group filtering
The three aggregate endpoints (/onboarding, /courses, /journeys) accept an optional group_ids filter.
| Query param | Notes |
|---|---|
group_ids | Optional. Comma-separated group IDs (e.g. 12,40). Counts are narrowed to users in the given departments / professions / custom groups. Unknown IDs return 422. |
Kiosk users are always excluded from academy figures.
/stats/academy/onboarding
Onboarding-flow completion totals across all non-kiosk users (narrowed by group_ids).
{
"data": {
"completed": 312,
"not_completed": 88
}
}/stats/academy/courses
Completion counts for every published course. Each course is counted against the users who can access it (its targeted groups), narrowed by group_ids.
{
"data": [
{
"id": 12,
"title": "Food Safety Basics",
"completed": 210,
"not_completed": 90
}
]
}/stats/academy/journeys
Completion totals for every published journey, including the onboarding flow.
{
"data": [
{
"id": 3,
"title": "Onboarding",
"type": "onboarding",
"completed": 312,
"not_completed": 88
},
{
"id": 7,
"title": "Leadership Track",
"type": "custom",
"completed": 41,
"not_completed": 19
}
]
}/stats/academy/quizzes/{quiz_id}
Per-question performance for a single quiz. pass_rate is the percentage of respondents who answered the question fully correctly. Returns 404 if the quiz does not exist or has been deleted.
{
"data": [
{
"question_id": 45,
"body": "At what core temperature is poultry safe to serve?",
"respondents": 120,
"passed": 96,
"pass_rate": 80
}
]
}/stats/academy/users/{user_id}/courses
A single user's progress across the published courses assigned to them. Resolves active employees only — kiosk, bot, shadow and banned users return 404, as does an unknown id.
| Field | Notes |
|---|---|
course_id | The course's id. |
title | The course title. |
has_passed | true when the user has passed the course (or it is awaiting manual sign-off). |
completed_at | ISO-8601 completion timestamp, or null if not completed. |
chapters_completed_count | Number of chapters the user has completed (respects completion resets). |
awaits_manual_completion | true when the user has met the requirements but the course needs manual sign-off. |
{
"data": [
{
"course_id": 12,
"title": "Food Safety Basics",
"has_passed": true,
"completed_at": "2026-05-01T10:00:00+00:00",
"chapters_completed_count": 4,
"awaits_manual_completion": false
}
]
}/stats/academy/users/{user_id}/onboarding
A single user's onboarding status. Resolves active employees only — kiosk, bot, shadow and banned users return 404, as does an unknown id.
| Field | Notes |
|---|---|
onboarding_completed_at | ISO-8601 timestamp the user completed onboarding, or null if not completed. |
is_overdue | true when the user has not completed onboarding within the configured time limit. |
onboarding_days | Days left to complete onboarding (negative when overdue), or null if no onboarding time limit is configured. |
{
"data": {
"onboarding_completed_at": "2026-05-01T10:00:00+00:00",
"is_overdue": false,
"onboarding_days": 12
}
}