Pull engagement reports with the API

The Engagement requests: your headline numbers, engagement per course and module, student activity and watch history, and where viewers drop off lessons.

The Engagement part of the API answers "who is learning, how far do they get, and where do they stop watching?" It gives you your school's headline numbers in one call, engagement per course and module, each student's activity and watch history, and the lessons where viewers drop off. Use it to feed a dashboard or a weekly report.

Who can do this

  • A tool holding a key from Settings → API keys. Every Settings key can make the read requests here.
  • The workspace must be on a paid plan (Core, Advanced or Professional) and in service.
  • Keys created in Settings can't make the four requests that change data (last section).

Every request goes to https://app.zinstruct.com with Authorization: Bearer and your key; see Call the API.

Get your headline numbers

  1. Send GET /api/reporting/v1/summary.
  2. You get one object: students, active_students_30d, paying_customers, courses, modules, lessons, logins_30d, avg_session_minutes, lessons_watched_over_30s_30d and completion_rate_pct.
The Get the KPI summary entry in the API reference

It's the cheapest call for a dashboard tile.

See engagement per course and module

  1. Send GET /api/reporting/v1/courses for every course, a page at a time. Each has modules_count, lessons_count, students_enrolled, lessons_watched_over_30s, distinct_students_watched and avg_completion_pct.
  2. Send GET /api/reporting/v1/courses/{course_id}/modules for one course's modules in their display order, each with its lesson count and watch activity.

See what each student is doing

  1. Send GET /api/reporting/v1/students. Filter with ?role=, and add ?sort=last_active_at to put the most recently active first.
  2. Each student has name, email, role, joined_at, last_active_at, logins_30d, avg_session_minutes, total_session_minutes_30d, paying and lifetime_revenue_cents.
  3. Fetch one with GET /api/reporting/v1/students/{student_id}.
  4. Send GET /api/reporting/v1/students/{student_id}/watch-history for every lesson that student has watched, newest first, with watched_seconds, watched_pct and last_watched_at.
The List students with activity entry in the API reference with its role and sort parameters

Find where viewers drop off

  1. Send GET /api/reporting/v1/lessons?sort=worst_retention&limit=10. Lessons are ranked by how early in the lesson viewers drop off sharply. limit is 1 to 100, default 10. Lessons with no recorded viewing are left out.
  2. Send GET /api/reporting/v1/lessons/{lesson_id}/retention for one lesson: views, avg_watch_seconds, avg_watch_pct, the retention curve and biggest_dropoff.
The Rank lessons by earliest drop-off entry in the API reference with its sort and limit parameters

Use the result to decide which lesson to re-record or shorten first.

Requests that change data

The reporting API also has four requests that change data:

  • update a student's role, status (active or archived) or tags;
  • add a note to a student;
  • flag a lesson for review, with an improvement note;
  • email a student a nudge to come back.

They need a key with the write scope. Keys created in Settings → API keys are read-only, so these requests are refused with "This token lacks the 'write' scope." and they're left out of the reference.

A key that does have the write scope can send an Idempotency-Key header (8 to 200 characters) with these requests, so a retried request isn't applied twice: a repeat gets the first reply back, marked Idempotency-Replayed: true. The nudge email needs that header, and works only on accounts where nudges are switched on. Changes made this way don't trigger automations or webhooks.

What happens next

  • Each accepted request updates the key's Last used time.
  • Engagement numbers come from what students watch and how they sign in to the member area. A school with no recorded viewing returns zeros and empty lists.
  • Nothing is changed or sent by the read requests.

Common errors

  • "Course not found.", "Student not found." or "Lesson not found." (404): the id doesn't exist in this workspace.
  • "Only ?sort=worst_retention is supported on /lessons." (400, bad_request): leave sort out or set it to worst_retention.
  • "Could not build the summary." (500, internal_error): a temporary problem on our side. Retry shortly.
  • "This token lacks the 'write' scope." (403, forbidden): the request changes data, and Settings keys can only read.
  • "Invalid or revoked token." (401) or "Too many requests. Slow down." (429): see Call the API.

Related articles

Still stuck? Talk to a human.

Email support@zinstruct.com. We reply within one business day, Monday to Friday, 9 a.m. to 5 p.m. US Mountain Time. Already signed in? Ask from the help button inside the app.

Email support