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

GET
/api/open/v1/stats/academy/onboarding

Onboarding completion totals

GET
/api/open/v1/stats/academy/courses

Completion rates per published course

GET
/api/open/v1/stats/academy/journeys

Completion totals per published journey

GET
/api/open/v1/stats/academy/quizzes/{quiz_id}

Per-question quiz performance summary

GET
/api/open/v1/stats/academy/users/{user_id}/courses

A single user's course progress

GET
/api/open/v1/stats/academy/users/{user_id}/onboarding

A single user's onboarding status

Group filtering

The three aggregate endpoints (/onboarding, /courses, /journeys) accept an optional group_ids filter.

Query paramNotes
group_idsOptional. 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.

FieldNotes
course_idThe course's id.
titleThe course title.
has_passedtrue when the user has passed the course (or it is awaiting manual sign-off).
completed_atISO-8601 completion timestamp, or null if not completed.
chapters_completed_countNumber of chapters the user has completed (respects completion resets).
awaits_manual_completiontrue 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.

FieldNotes
onboarding_completed_atISO-8601 timestamp the user completed onboarding, or null if not completed.
is_overduetrue when the user has not completed onboarding within the configured time limit.
onboarding_daysDays 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
  }
}