Skip to main content
The drop-off prediction endpoints read live from the BigQuery warehouse (mlip_dropoff_prediction_synth.student_dashboard_30d) — this data is not stored in the MIND database; each request queries BigQuery directly (with a short server-side cache). All endpoints require STUDENT_PERFORMANCE.can_view permission.
How risk bands are derived. The model emits risk_level of High / Medium / Low plus a drop_off_score. The dashboard adds a Critical band as the top slice of High (drop_off_score ≥ critical cutoff, default 0.50). Because the synthetic drop_off_score tops out around 0.55, the table’s threshold column (0.7) is not used for flagging — the calibrated cutoffs are: flagged ≥ 0.15, high ≥ 0.40, critical ≥ 0.50 (all configurable).

Get Aggregate Dashboard Stats

GET /v1/console/student-dropoff/stats
Summary cards for the At-Risk Students dashboard: total flagged, and Critical / High / Medium counts, each with the change vs the previous model run.

Query parameters

faculty
string
Filter by faculty.
programme
string
Filter by programme.
year
string
Filter by programme level (e.g. 100L, 300L).
cohort
string
Filter by cohort (e.g. 202402_S1).
period
datetime
Model-run timestamp to report on. Defaults to the latest run. When a non-latest run is requested, card counts are derived from drop_off_score (basis scores) rather than the model labels (basis labels).
risk_level
string
Accepted for API symmetry. The band cards always show the full breakdown, so this does not change the aggregate counts (it scopes the at-risk list).

Example request

curl "https://staging-be.mind.miva.university/v1/console/student-dropoff/stats?faculty=Computing" \
  -H "Authorization: Bearer <access_token>"

Response

{
  "success": true,
  "data": {
    "total_students": 10000,
    "total_flagged": { "count": 3000, "pct_change": -0.2886 },
    "critical": { "count": 284, "pct_change": -0.0105 },
    "high": { "count": 716, "pct_change": -0.1848 },
    "medium": { "count": 2000, "pct_change": -0.3243 },
    "current_period": "2026-05-29T07:59:13.935658Z",
    "previous_period": "2026-05-26T07:59:13.935658Z",
    "cards_basis": "labels",
    "thresholds": {
      "model_threshold": 0.7,
      "flagged_score_cutoff": 0.15,
      "high_score_cutoff": 0.40,
      "critical_score_cutoff": 0.50,
      "labels": ["critical", "high", "medium", "low"]
    },
    "filters": { "faculty": "Computing" }
  },
  "message": null
}

Field reference

FieldDescription
total_flagged / critical / high / medium{ count, pct_change }. pct_change is a fraction (-0.2886 = −28.86%) vs the previous run, derived from run_history scores. null when there is no prior run.
cards_basislabels (counts from the model’s risk_level on the latest snapshot) or scores (score-derived, for a historical period).
current_period / previous_periodModel-run timestamps used for the comparison.
thresholdsThe calibrated cutoffs in effect, plus the informational model threshold.

Get Filter Options

GET /v1/console/student-dropoff/filter-options
Distinct values for the dashboard filter controls.

Response

{
  "success": true,
  "data": {
    "faculties": ["Allied Health Sciences", "Communication & Media Studies", "Computing", "Management"],
    "programmes": ["BSc Accounting", "BSc Computer Science", "..."],
    "years": ["100L", "200L", "300L", "400L", "500L"],
    "cohorts": ["202401_S1", "202402_S1", "202402_S2", "202501_S1"],
    "periods": ["2026-05-29T07:59:13.935658Z", "2026-05-26T07:59:13.935658Z"]
  },
  "message": null
}

Predicted Drop-off Over Time

GET /v1/console/student-dropoff/trend
Time series of flagged / critical / high / medium counts per model run, for the “Predicted Drop-off Over Time” chart. Counts are score-derived from run_history so they are consistent across runs.

Query parameters

window
string
default:"all"
this_week, this_month, last_month, this_quarter, last_quarter, this_year, last_year, or all. Windows are relative to the latest run.
faculty
string
Filter by faculty.
programme
string
Filter by programme.
year
string
Filter by programme level.
cohort
string
Filter by cohort.

Response

{
  "success": true,
  "data": {
    "window": "this_month",
    "since": "2026-04-29T07:59:13.935658Z",
    "until": "2026-05-29T07:59:13.935658Z",
    "points": [
      { "run_ts": "2026-05-01T07:59:13.935658Z", "flagged": 7972, "critical": 3108, "high": 1100, "medium": 3764, "total": 10000 },
      { "run_ts": "2026-05-29T07:59:13.935658Z", "flagged": 3000, "critical": 284, "high": 716, "medium": 2000, "total": 10000 }
    ],
    "filters": {}
  },
  "message": null
}
Trend counts are score-derived (cutoffs flagged ≥0.15, high ≥0.40, critical ≥0.50), so they reconcile with the latest aggregate cards at the most recent run but use scores — not labels — for earlier runs (which have no stored label).

List At-Risk Students

GET /v1/console/student-dropoff/students
Paginated list of at-risk students for the dashboard, using the same filters as the summary cards. Defaults to the flagged population (High + Medium); narrow with risk_level.

Query parameters

faculty
string
Filter by faculty.
programme
string
Filter by programme.
year
string
Filter by programme level (e.g. 300L).
cohort
string
Filter by cohort.
risk_level
string
critical, high, medium, or low. Omit to return all flagged students (High + Medium).
period
datetime
Run timestamp. Defaults to the latest run. A historical run is re-scored from run_history (band derived from score; risk_level label is omitted for past runs).
Match on name, email, student id, or programme (case-insensitive).
sort_by
string
default:"drop_off_score"
drop_off_score, days_since_last_activity, or fullname.
sort_order
string
default:"desc"
asc or desc.
skip
integer
default:"0"
Records to skip.
limit
integer
default:"20"
Max records (1-100).

Example request

curl "https://staging-be.mind.miva.university/v1/console/student-dropoff/students?risk_level=critical&faculty=Computing&limit=20" \
  -H "Authorization: Bearer <access_token>"

Response

{
  "success": true,
  "data": [
    {
      "student_id": "STU001027",
      "fullname": "Jane Doe",
      "student_email": "jane.doe@miva.university",
      "faculty": "Management",
      "programme": "BSc Accounting",
      "program_level": "300L",
      "current_cohort": "202402_S1",
      "risk_level": "High",
      "risk_band": "critical",
      "drop_off_score": 0.5499,
      "score_trend_slope": 0.012,
      "trajectory": "worsening",
      "risk_reasons": ["No content completion in 14d", "Missed deadlines in last 30d"],
      "days_since_last_activity": 14,
      "missed_deadline": true,
      "n_courses": 4,
      "n_high_courses": 2,
      "latest_scored_at": "2026-05-29T07:59:13.935658Z"
    }
  ],
  "total": 284,
  "page": 1,
  "page_size": 20,
  "total_pages": 15,
  "message": null
}
risk_reasons powers the “Key signals” chips on each row.

Export At-Risk Students

GET /v1/console/student-dropoff/students/export
Download the current filtered list as CSV or XLSX. Uses the same filters, risk_level, search, and sort as the list endpoint.

Query parameters

format
string
default:"csv"
csv or xlsx.
Plus faculty, programme, year, cohort, risk_level, search, sort_by, sort_order.

Response

A file download. Columns: Student Name, Student ID, Email, Programme, Faculty, Year, Risk Band, Risk Score, Days Inactive, Missed Deadline, Key Signals, Last Scored. Filename: at_risk_students_{YYYY-MM-DD}.{csv|xlsx}. Hard cap of 50,000 rows.

Get Student Risk Profile & Trend

GET /v1/console/student-dropoff/students/{student_id}
The full risk profile for one student: current band and drivers, confidence (drop_off_score), risk trajectory, behavioural / academic / payment signals, per-course risk, and the full 24-run score trend.

Path parameters

student_id
string
required
The student’s ID (BigQuery student_id).

Example request

curl "https://staging-be.mind.miva.university/v1/console/student-dropoff/students/STU-000123" \
  -H "Authorization: Bearer <access_token>"

Response

{
  "success": true,
  "data": {
    "student_id": "STU-000123",
    "fullname": "Jane Doe",
    "student_email": "jane.doe@miva.university",
    "program": "BSc Computer Science",
    "program_level": "300L",
    "faculty": "Computing",
    "current_cohort": "202402_S1",
    "week_of_session": 9,
    "risk_level": "High",
    "risk_band": "critical",
    "drop_off_score": 0.5499,
    "confidence": 0.5499,
    "threshold": 0.7,
    "risk_reasons": ["No content completion in 14d", "Low engagement (logins below 7d band)"],
    "score_trend_slope": -0.0007,
    "trajectory": "stable",
    "risk_score_delta": 0.1083,
    "missed_deadline": true,
    "days_since_last_activity": 12,
    "engagement_level": "low",
    "missed_assessments": 3,
    "behavior": {
      "login_days_7d": 1, "login_days_30d": 4, "active_days_30d": 3,
      "learning_mins_30d": 45, "content_completed_30d": 0, "submissions_30d": 0
    },
    "academic": {
      "avg_total_score": 41.2, "avg_exam_score": 38.0, "pct_exams_completed": 0.5,
      "avg_grade_point": 1.8, "n_exams_total": 4, "best_exam_score": 55.0
    },
    "payment": {
      "payment_risk": 0.6, "payment_status": "Outstanding",
      "expected_amount": 450000.0, "amount_due": 200000.0, "balance": 200000.0
    },
    "courses": [
      {
        "course_code": "CSC401",
        "course_name": "Operating Systems",
        "risk_level": "High",
        "model_risk_level": "High",
        "drop_off_score": 0.5499,
        "review_priority": "P1",
        "factor_chips": ["↑ missed_deadline_30d", "↓ active_days_30d", "↓ login_days_30d"],
        "missed_deadline": true,
        "days_since_last_activity": 12
      }
    ],
    "trend": [
      { "model_run_id": "20260407T075913Z", "run_ts": "2026-04-07T07:59:13.935658Z", "drop_off_score": 0.4776, "risk_band": "high", "delta_vs_previous": null },
      { "model_run_id": "20260529T075913Z", "run_ts": "2026-05-29T07:59:13.935658Z", "drop_off_score": 0.5499, "risk_band": "critical", "delta_vs_previous": 0.1083 }
    ],
    "model_run_id": "20260529T075913Z",
    "model_version": "1.3.0-synth",
    "score_date": "2026-05-29",
    "latest_scored_at": "2026-05-29T07:59:13.935658Z"
  },
  "message": null
}

Notes

  • confidence is the model’s drop_off_score (probability of drop-off).
  • trajectory is derived from score_trend_slope: worsening (rising risk), improving, or stable.
  • risk_score_delta is the change in drop_off_score from the previous run to the latest.
  • engagement_level (low/medium/high) is derived from 30-day active/login days.
  • missed_assessments counts the student’s courses with a missed deadline.
  • trend contains only real runs — the warehouse pads run_history to a fixed length with empty entries, which are dropped.
  • 404 NOT_FOUND if the student is not in the drop-off dataset.

Get Prediction History

GET /v1/console/student-dropoff/students/{student_id}/history
Chronological history of ML prediction runs for a student — risk trajectory over time, with the band and score delta at each run.

Path parameters

student_id
string
required
The student’s ID.

Response

{
  "success": true,
  "data": {
    "student_id": "STU-000123",
    "fullname": "Jane Doe",
    "score_trend_slope": -0.0007,
    "trajectory": "stable",
    "runs": [
      { "model_run_id": "20260407T075913Z", "run_ts": "2026-04-07T07:59:13.935658Z", "drop_off_score": 0.4776, "risk_band": "high", "delta_vs_previous": null },
      { "model_run_id": "20260411T075913Z", "run_ts": "2026-04-11T07:59:13.935658Z", "drop_off_score": 0.4900, "risk_band": "high", "delta_vs_previous": 0.0124 }
    ]
  },
  "message": null
}

Field reference

FieldDescription
runs[].risk_bandScore-derived band for that run (critical/high/medium/low).
runs[].delta_vs_previousChange in drop_off_score from the prior run; null for the first run.
trajectoryOverall direction from score_trend_slope.