Skip to content

API — Dashboard REST

The dashboard API exposes reads over the processed data in SoftSys Edu Analytics. It is used internally by the web dashboard, but it can also be consumed from your own integrators (backends, BI tools, mobile apps) that want to build their own experience on top of tenant data.

https://api.softsysanalytics.com

The dashboard API accepts two modes:

  1. Authorization: Bearer <jwt> — session JWT obtained via SSO exchange from the Moodle plugin.
  2. X-SSEA-Key: ssea_<key> — tenant-scoped API key, for service-to-service calls (backend integrators).

Bearer JWT is the mode the web dashboard (React) uses. X-SSEA-Key is the recommended mode for your own integrators.

Exchange a token signed by the Moodle plugin for a dashboard session JWT. Used by the standard SSO flow; regular integrators do not need it.

Request:
{
"token": "<jwt_signed_by_moodle_plugin>"
}
Response 200:
{
"ok": true,
"data": {
"token": "<dashboard_session_jwt>",
"tenant_id": "<tenant_uuid>",
"expires_at": "2026-04-13T16:30:00Z"
}
}

High-level metrics for the tenant. Used by the dashboard home.

Query params: days (int, default 30) — window in days.

Ventana de terminal
curl -H "X-SSEA-Key: ssea_<your_key>" \
"https://api.softsysanalytics.com/v1/tenants/<tenant_id>/overview?days=30"

Response 200:

{
"tenant_id": "<tenant_uuid>",
"period_days": 30,
"total_events": 45231,
"active_users": 312,
"total_sessions": 1842,
"avg_time_spent_mins": 34.5,
"at_risk_count": 17
}

Time series for trend charts (events per day/hour).

Paginated list of users with their activity summary.

Query params:

  • limit (int, default 50, max 200)
  • offset (int, default 0)
  • risk_level (optional): low | medium | high | critical

Response 200:

[
{
"user_id": "user_1",
"username": "jdoe",
"full_name": "Jane Doe",
"last_seen_at": "2026-03-23T18:30:00Z",
"total_events": 142,
"total_time_mins": 87,
"risk_level": "low",
"risk_score": 12.4
}
]

Detailed profile for a user with activity history and daily timeline.

Top users and courses by event volume (short list for widgets).

Activity heatmap by hour and day of week.

List of courses with engagement metrics.

Response 200:

[
{
"course_id": "course_1",
"fullname": "Introduction to Python",
"shortname": "CS101",
"active_users": 87,
"total_events": 3421,
"avg_time_mins": 42.1
}
]

List of at-risk students with score and factors.

Query params:

  • course_id (optional): filter by course.
  • risk_level (optional): filter by level.
  • limit, offset, sort (e.g. score_desc).

Response 200:

[
{
"user_id": "user_42",
"username": "mjones",
"full_name": "Mike Jones",
"risk_level": "high",
"risk_score": 73.2,
"last_seen_at": "2026-03-15T10:00:00Z",
"days_inactive": 9,
"completion_pct": 18.5,
"acknowledged": false
}
]

POST /v1/tenants/:id/at-risk/:userId/acknowledge

Section titled “POST /v1/tenants/:id/at-risk/:userId/acknowledge”

Mark a student’s risk flag as seen/handled. Useful for a teacher to note they already took action.

Response 200:

{ "ok": true }

List of active alerts (inactivity, performance drops, completion milestones, etc.).

Query params: include_acknowledged (bool, default false).

Response 200:

[
{
"alert_id": "alrt_abc123",
"user_id": "user_42",
"alert_type": "inactivity",
"severity": "high",
"message": "User has been inactive for 9 days",
"triggered_at": "2026-03-24T01:00:00Z",
"acknowledged": false
}
]

POST /v1/tenants/:id/alerts/:alertId/acknowledge

Section titled “POST /v1/tenants/:id/alerts/:alertId/acknowledge”

Acknowledge a single alert.

POST /v1/tenants/:id/alerts/acknowledge-all

Section titled “POST /v1/tenants/:id/alerts/acknowledge-all”

Acknowledge all pending alerts for the tenant.

Aggregated enrollment stats by course and role.

Grade distribution (avg, min, max) at tenant level.

GET /v1/tenants/:id/courses/:courseId/grades

Section titled “GET /v1/tenants/:id/courses/:courseId/grades”

Grade analytics for a specific course.

Aggregated completion rate by course.

GET /v1/tenants/:id/courses/:courseId/completion

Section titled “GET /v1/tenants/:id/courses/:courseId/completion”

Completion by activity within a course.

For exports that may take time (e.g. retention cohorts, performance analysis), SSEA offers an async job flow: create a job, poll its status, and download the artifact when it’s ready.

Create a report job.

Request body:

{
"report_type": "retention_cohort",
"format": "csv",
"params": {
"date_from": "2026-01-01",
"date_to": "2026-03-31",
"max_weeks": 12
}
}

report_type values:

  • retention_cohort — retention by enrollment cohort.
  • activity_funnel — completion funnel by activity.
  • teacher_course_health — course health from the teacher’s perspective.
  • student_learning_profile — aggregated student profile.
  • assessment_performance — assessment performance.
  • early_warning_summary — early warning summary.

Supported formats: csv (default) or json.

Response 202:

{
"job_id": "job_xyz",
"status": "pending",
"requested_at": "2026-04-13T14:00:00Z"
}

List the tenant’s jobs (options: status, limit, offset).

Check a job’s status.

Response 200:

{
"job_id": "job_xyz",
"status": "completed",
"requested_at": "2026-04-13T14:00:00Z",
"completed_at": "2026-04-13T14:01:23Z",
"artifacts": [
{ "format": "csv", "url": "<signed_url>", "expires_at": "..." }
]
}

Possible states: pending, running, completed, failed, expired.

GET /v1/tenants/:id/reports/jobs/:jobId/download

Section titled “GET /v1/tenants/:id/reports/jobs/:jobId/download”

Download the report artifact. Redirects to a signed URL (Cloudflare R2) or returns the content inline depending on configuration.

Monitors are user-saved filters — useful for tracking a specific group of students or courses.

  • GET /v1/tenants/:id/monitors — list monitors.
  • POST /v1/tenants/:id/monitors — create a new monitor.
  • DELETE /v1/tenants/:id/monitors/:id — delete a monitor.

Viewer endpoints let a student or teacher see their own data from an iframe inside Moodle, without holding a dashboard JWT. They require the X-SSEA-Viewer-Context and X-SSEA-Viewer-Signature headers (see Security & privacy).

  • GET /v1/tenants/:id/viewer/student/:moodleUserId/profile — student’s profile.
  • GET /v1/tenants/:id/viewer/student/:moodleUserId/progress — progress by course and activity.
  • GET /v1/tenants/:id/viewer/student/:moodleUserId/alerts — the student’s own alerts.
  • GET /v1/tenants/:id/viewer/teacher/:moodleUserId/courses/health — health of their courses, at-risk counts.
  • GET /v1/tenants/:id/viewer/teacher/:moodleUserId/students/at-risk — at-risk students in their courses.

Public branding — resolved by the Host header (useful for white-label with custom domain). No authentication required.

Response 200:

{
"logo_url": "<r2_signed_url>",
"primary_color": "#4f46e5",
"product_name": "Acme Analytics"
}

Branding for the authenticated tenant.

HTTPMeaning
200OK.
204CORS preflight.
400Invalid request or query params.
401Missing, invalid, or expired token.
403Cross-tenant — the authenticated token does not match the path tenant.
404Resource not found.
422Payload validation failed.
429Rate limit exceeded.
503Worker misconfigured.

Error format:

{
"ok": false,
"error": "Human-readable message",
"code": "ERROR_CODE"
}