mobieusCore API — mobieusLearn
The Learn surface of the public REST API. Manage courses, modules, lessons, activities, enrollments, attempts, certificates, certificate templates, and SCORM packages.
Added in API version 1.3.0 (2026-06-02).
Scopes
| Scope | Grants |
|---|---|
learn:read |
List + read every Learn resource (courses, enrollments, attempts, certificates, templates, SCORM packages, nested entities). |
learn:write |
Create / update / publish / archive courses, enroll users, cancel enrollments, revoke + regenerate certificates. |
learn:cohorts:grant |
Grant cohort access via POST /api/v1/learn/cohorts/grant. |
Generate a key at /admin/api-keys, tick the scopes you need.
Pro / Creator Plus / Sovereign plans only — same plan gate as the
rest of the public API.
Quick start
curl https://YOUR-TENANT.mobieus.io/api/v1/learn/courses \
-H 'Authorization: Bearer mc_live_...'
Returns up to 50 courses ordered by id desc. Use ?cursor=...&limit=N
(max 100) to page; next_cursor is null on the last page.
Resources
Courses
| Method | Path | Scope | What |
|---|---|---|---|
GET |
/api/v1/learn/courses |
learn:read |
List courses (cursor-paginated). |
GET |
/api/v1/learn/courses/{id} |
learn:read |
Get a single course (with credit info, version status, owner author). |
POST |
/api/v1/learn/courses |
learn:write |
Create a course. Required: slug, title. Optional: subtitle, summary, language, completion_rule, estimated_minutes, credit_hours, credit_kind, credit_expires_after_months. |
POST |
/api/v1/learn/courses/{id} |
learn:write |
Update. Any field from create is acceptable; omitted fields keep their value. |
POST |
/api/v1/learn/courses/{id}/publish |
learn:write |
Move to published. |
POST |
/api/v1/learn/courses/{id}/unpublish |
learn:write |
Revert to draft. |
POST |
/api/v1/learn/courses/{id}/archive |
learn:write |
Archive (hides from learners; preserves enrollments). |
Example: enroll-on-purchase flow
# 1. Create a course
curl -X POST https://YOUR-TENANT.mobieus.io/api/v1/learn/courses \
-H 'Authorization: Bearer mc_live_...' -H 'Content-Type: application/json' \
-d '{"slug":"intro-to-mobieus","title":"Intro to Mobieus","completion_rule":"all_required","credit_hours":2.5,"credit_kind":"CEU"}'
# 2. After a Stripe checkout completes, enroll the buyer
curl -X POST https://YOUR-TENANT.mobieus.io/api/v1/learn/enrollments \
-H 'Authorization: Bearer mc_live_...' -H 'Content-Type: application/json' \
-d '{"user_id":123,"course_id":42,"source":"stripe_purchase"}'
Nested entities (read-only)
| GET | /api/v1/learn/courses/{id}/modules | learn:read | Modules in a course. |
| GET | /api/v1/learn/modules/{mid}/lessons | learn:read | Lessons in a module. |
| GET | /api/v1/learn/lessons/{lid}/activities | learn:read | Activities in a lesson. |
Writes for modules / lessons / activities go through the admin UI; they enforce per-course team membership. Per-course capability scoping for the API key model lands in a future minor version.
Enrollments
| GET | /api/v1/learn/enrollments?course_id=&user_id= | learn:read | List, optionally filtered. |
| GET | /api/v1/learn/enrollments/{id} | learn:read | Get one. |
| POST | /api/v1/learn/enrollments | learn:write | Enroll a user. Body: {"user_id", "course_id", "source"?, "expires_at"?}. |
| POST | /api/v1/learn/enrollments/{id}/cancel | learn:write | Cancel (status flips to cancelled). |
Cohorts
| POST | /api/v1/learn/cohorts/grant | learn:cohorts:grant | Grant a user access to a cohort. |
Attempts
| GET | /api/v1/learn/attempts?enrollment_id=&activity_id= | learn:read | List. |
| GET | /api/v1/learn/attempts/{id} | learn:read | Get one (includes score_raw, score_scaled, passed, status, time_started_at, time_ended_at, total_time_seconds). |
Certificates
| GET | /api/v1/learn/certificates?user_id=&course_id= | learn:read | List. |
| GET | /api/v1/learn/certificates/{id} | learn:read | Get one. |
| GET | /api/v1/learn/certificates/verify/{vid} | learn:read | Look up by the 40-char verification id. Returns is_revoked: true|false. |
| POST | /api/v1/learn/certificates/{id}/revoke | learn:write | Revoke. Body: {"reason": "..."}. Required. |
| POST | /api/v1/learn/certificates/{id}/regenerate-pdf | learn:write | Rebuild the PDF (after editing a template). Verification URL unchanged. |
Certificate templates
| GET | /api/v1/learn/cert-templates | learn:read | List templates (per-tenant brand identity for certs). |
| GET | /api/v1/learn/cert-templates/{id} | learn:read | Get one. |
SCORM packages
| GET | /api/v1/learn/scorm-packages | learn:read | List packages (any status). |
| GET | /api/v1/learn/scorm-packages/{id} | learn:read | Get one with its SCO list. |
Importing a SCORM package via API isn't supported in 1.3.0 — use the
admin UI at /admin/learn/scorm/new. The endpoint is on the roadmap.
Response envelope
Every endpoint returns:
{
"data": ...,
"next_cursor": "...",
"request_id": "req_..."
}
next_cursor is null when there's no more data.
Errors
Errors use the standard v1 envelope — a single error object with a
code, a message, and the request_id:
{
"error": {
"code": "course_not_found",
"message": "Course not found.",
"request_id": "req_..."
}
}
Common codes for the Learn surface:
| Code | When |
|---|---|
404 course_not_found |
id doesn't match any row. |
404 enrollment_not_found |
Same for enrollments. |
404 certificate_not_found |
Same for certs (including /verify/{vid} misses). |
400 invalid_argument |
The course service rejected the payload — message explains. |
400 missing_field |
A required body field was empty / absent. |
403 insufficient_scope |
Key doesn't have learn:read (or learn:write). |
What's not in 1.3.0 (defer to a future minor)
- Import SCORM packages via API (use the admin UI today).
- Assessment item authoring + question-bank CRUD via API.
- Question pool CRUD via API.
- Per-course team membership for API keys (today they get tenant-wide admin-equivalent capabilities).
Discussion
Sign in to start the discussion.