API Overview
OptiLearn's REST API structure and conventions
OptiLearn exposes 100+ REST endpoints across courses, learners, assessments, notifications, parents, peer review, captions, recording, analytics, and integrations. The API follows a single response envelope and shared error vocabulary.
Base URL
https://learn.opticrm.app/api
Authentication
All API routes (except public ones like certificate verification, NextAuth, and the Jibri webhook) require an authenticated session. OptiLearn uses the same JWT cookie as OptiCRM:
Cookie: __Secure-authjs.session-token=<jwt>
Requests without a valid session return 401 Unauthorized. Mobile clients use bearer tokens via /api/v1/* (separate doc, mobile auth).
Response Format
All responses use a consistent envelope:
Success
{
"data": { ... },
"error": null,
"meta": {
"total": 42,
"page": 1,
"perPage": 12,
"totalPages": 4
}
}
meta is only present for paginated endpoints.
Error
{
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": { ... }
}
}
Error Codes
| Code | HTTP | Meaning |
|---|---|---|
AUTH_REQUIRED | 401 | Not authenticated |
FORBIDDEN | 403 | Authenticated but lacks permission |
NOT_FOUND | 404 | Resource doesn't exist |
VALIDATION_ERROR | 400 | Invalid request body or params |
TENANT_MISMATCH | 403 | institutionId doesn't match JWT |
ENROLLMENT_REQUIRED | 403 | Must be enrolled in the course |
ALREADY_ENROLLED | 409 | Already enrolled |
COURSE_FULL | 409 | Max enrollments reached |
ATTEMPT_LIMIT | 409 | Max quiz attempts reached |
LESSON_LOCKED | 403 | Drip content not yet unlocked |
FEE_OVERDUE | 402 | Fee gating blocked the action |
INTERNAL_ERROR | 500 | Server error |
Endpoint Categories
Courses & Content
GET /api/courses— List courses with filtersPOST /api/courses— Create a courseGET /api/courses/[id]— Get course detailPATCH /api/courses/[id]— Update courseDELETE /api/courses/[id]— Archive coursePOST /api/courses/[id]/publish— Change publish statusPOST /api/courses/[id]/duplicate— Duplicate a courseGET/POST /api/courses/[id]/modules— List/create modulesPOST /api/courses/[id]/lessons— Create a lessonGET/POST /api/courses/[id]/announcements— Announcements (class-targetable)GET/POST /api/courses/[id]/discussions— Course forumPATCH/DELETE /api/modules/[id]— Update/delete moduleGET/PATCH/DELETE /api/lessons/[id]— Lesson CRUD
Lesson Engagement (per-lesson)
GET/POST /api/lessons/[id]/notes— Student notesGET/PATCH/DELETE /api/lessons/[id]/notes/[noteId]GET/POST /api/lessons/[id]/bookmarksGET/PATCH/DELETE /api/lessons/[id]/bookmarks/[bookmarkId]GET/POST /api/lessons/[id]/captions— WebVTT caption tracksPATCH/DELETE /api/lessons/[id]/captions/[captionId]GET /api/lessons/[id]/captions/[captionId]/transcript— parsed cuesGET/POST /api/lessons/[id]/discussionsGET/POST /api/lessons/[id]/blocks/[blockId]/answer— interactive block answersPOST /api/lessons/[id]/events— learner eventsPOST /api/lessons/[id]/interactionsPOST /api/lessons/[id]/pdf-progressPOST /api/lessons/[id]/progress/progress-v2
See Notes & Bookmarks API and Captions API.
Aggregate "My" Endpoints
GET /api/me/notes— every note the student has taken (paginated)GET /api/me/bookmarks— every bookmarkGET /api/me/peer-reviews— peer-review queue
Enrollment & Progress
POST /api/courses/[id]/enroll— Self-enrollGET/POST /api/courses/[id]/enrollments— List / bulk enrollGET/DELETE /api/courses/[id]/enrollments/[studentId]— Detail / unenrollPOST /api/lessons/[id]/progress— Update lesson progress
Assessment & Peer Review
GET/PUT /api/quiz/[id]— Get / upsert quizPOST /api/quiz/[id]/attempt— Submit quiz attemptGET /api/quiz/[id]/attempts— List attemptsGET/PUT /api/assignments/[id]— Get / upsert assignmentPOST /api/assignments/[id]/submit— Submit assignmentPOST /api/assignments/[id]/grade— Grade a submissionGET /api/assignments/[id]/submissions— List submissionsGET /api/assignments/[id]/peer-reviews— Instructor moderation viewGET/PATCH /api/peer-reviews/[id]— Reviewer detail / draftPOST /api/peer-reviews/[id]/submit— Final submitPOST /api/peer-reviews/[id]/flag— Flag inappropriate work
See Peer Reviews API.
Live Sessions & Recording
GET/POST /api/live-sessionsPOST /api/live-sessions/[id]/startPOST /api/live-sessions/[id]/endPOST /api/live-sessions/[id]/joinPOST /api/live-sessions/[id]/registerPOST /api/live-sessions/[id]/attendanceGET /api/live-sessions/[id]/icsPOST /api/live-sessions/[id]/recording/start— Jibri start (host only)POST /api/live-sessions/[id]/recording/stop— Jibri stopPOST /api/webhooks/jitsi-recording— public Jibri callback (HMAC)
See Recording API.
Notifications
GET /api/notifications— list IN_APP rowsPATCH /api/notifications/read— mark read ({ ids }or{ all: true })GET /api/notifications/unread-count— bell badge pollGET /api/notifications/preferences— preference rows + digest timesPATCH /api/notifications/preferences— upsert one rowDELETE /api/notifications/preferences— reset to defaultsPATCH /api/notifications/preferences/digest-times— daily/weekly delivery timePOST /api/notifications/push-token— register web push token
See Notifications API.
Parent Portal
GET /api/parent/children— children linked to the calling parentGET /api/parent/children/[childId]/overview— read-only dashboard
See Parent API.
Student-Facing
GET /api/catalogue— Browse published coursesGET /api/my-courses— My enrolled coursesGET /api/learn/[courseId]— Course nav dataGET /api/learn/[courseId]/[lessonId]— Lesson content
Gamification
GET /api/gamification/leaderboard— Rankings (period: all/month/week)GET /api/gamification/badges— Badge list with earned statusGET /api/gamification/streak— Current streak + recent pointsPOST /api/reviews— Submit a course review
Certificates
GET /api/certificates— List my certificatesGET /api/certificates/verify?code=— Public verification endpoint
Learning Paths
GET/POST /api/learning-pathsGET/PATCH /api/learning-paths/[id]POST /api/learning-paths/[id]/coursesPOST /api/learning-paths/[id]/enroll
Compliance & SCORM
GET/POST /api/compliance/trainingGET /api/compliance/recordsPOST /api/compliance/waiveGET /api/scorm/[id]/launchPOST /api/scorm/[id]/trackGET/POST /api/xapi/statements
Analytics
POST /api/analytics/reports/run— Execute a ReportDefinitionPOST /api/analytics/reports/export— Run + serialize as CSV/XLSX/PDFGET /api/analytics/entities— Entity registryGET/POST /api/analytics/reports— Saved reportsGET/PATCH/DELETE /api/analytics/reports/[id]GET/POST /api/analytics/reports/[id]/schedulesPATCH/DELETE /api/analytics/reports/schedules/[id]GET/POST /api/analytics/reports/[id]/alertsPATCH/DELETE /api/analytics/reports/alerts/[id]GET /api/cron/report-schedules— Hourly cron entryGET /api/cron/analytics-snapshot— Hourly snapshot + cache invalidationGET /api/cron/assignment-reminders— Hourly assignment reminder cronGET /api/analytics/dashboard/revenue— Bespoke revenue rollupGET /api/analytics/courses/[id]— Course meta + lesson engagement (legacy)POST /api/sync/opticrm— Push completions to OptiCRM
See the Analytics Engine developer reference.
Files
POST /api/upload— Get presigned upload URLGET/POST /api/files
Settings & Misc
GET/PATCH /api/settings— LMS settings (incl. fee gating toggle)GET/POST /api/categoriesGET /api/audit-log
Pagination
Paginated endpoints accept:
?page=1— Page number (1-indexed)?perPage=12(or?limit=) — Items per page (max 100)
Response includes meta with total, page, perPage, totalPages.
Rate Limiting
Hot endpoints carry per-user limits. Examples:
/analytics/reports/run— 30 / minute/analytics/reports/export— 10 / minute- General write endpoints — 30 / minute
- General read endpoints — 100 / minute
Exceeding the limit returns 429 Too Many Requests.
Public Endpoints
These don't require authentication:
/api/auth/*— NextAuth endpoints/api/certificates/verify?code=— Certificate verification/api/webhooks/*— External webhooks (Razorpay, Jibri recording — both signature-verified)/api/xapi/statements— xAPI LRS (uses Basic auth)
All other endpoints require a valid session.