API Documentation
EduNest LMS is a Next.js 16 (App Router) application. There is no separate API server — every endpoint is a route handler living under src/app/api/. They run on the same host as the storefront and admin panel, so the base URL is simply your site origin.
Base URL (local):
http://localhost:3000Base URL (production):https://your-domain.com
There are three families of endpoints, each authenticated differently:
| Family | Path prefix | Auth |
|---|---|---|
| Public / storefront | /api/v1/*, /api/license/status |
Open (no auth) |
| Customer / learner portal | /api/v1/portal/* |
Session cookie member_session (JWT) |
| Instructor | /api/v1/instructor/* |
Instructor session |
| Admin | /api/v1/admin/* |
Session cookie admin_token (JWT) + RBAC permission |
| Install wizard | /api/install/* |
First-run only, gated by the installer |
| Public REST API add-on | /api/v1/ext/api/v1/* |
Bearer edu_ API key + scope |
Authentication
EduNest uses cookie-based sessions for the first-party surfaces (storefront, portal, instructor, admin) and a separate bearer-key scheme for the optional public REST API add-on.
Admin session (admin_token)
Admins sign in at POST /api/v1/admin/auth/login. On success the server sets an HTTP-only admin_token cookie holding a signed JWT. Every /api/v1/admin/* route reads that cookie, and most write routes additionally enforce a permission (RBAC) via requirePermission(...) — there is no global middleware, the check is per-route.
POST /api/v1/admin/auth/login
Content-Type: application/json
{ "email": "admin@example.com", "password": "••••••••" }
| Endpoint | Purpose |
|---|---|
POST /api/v1/admin/auth/login |
Sign in → sets admin_token cookie |
POST /api/v1/admin/auth/logout |
Clear the admin session |
GET /api/v1/admin/auth/me |
Current admin + roles/permissions |
POST /api/v1/admin/auth/change-password |
Change password (clears session) |
Customer / learner session (member_session)
Learners register and verify via email OTP, then receive a member_session cookie (JWT). All /api/v1/portal/* routes require it.
| Endpoint | Purpose |
|---|---|
POST /api/v1/portal/auth/register |
Create an account + send email OTP |
POST /api/v1/portal/auth/verify-otp |
Verify OTP → set session cookie |
POST /api/v1/portal/auth/login |
Sign in → set session cookie |
POST /api/v1/portal/auth/logout |
Clear the session |
POST /api/v1/portal/auth/forgot · /reset |
Password reset via OTP |
GET /api/v1/portal/auth/social/:provider |
Start a social sign-in flow |
Public REST API add-on (bearer edu_ keys)
The REST API & Keys add-on (src/product/addons/api/) exposes a read-only data API authenticated by an API key rather than a session. Keys are issued under Admin → API Keys, are stored only as a SHA-256 hash, and carry scopes. Send the raw key either way:
Authorization: Bearer edu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-API-Key: edu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Each endpoint requires a scope; a key missing the scope is rejected with 403. The scopes are courses, customers, enrollments, orders (or * for all).
| Status | Meaning |
|---|---|
401 |
Missing, invalid, or revoked API key |
403 |
Key is missing the endpoint's scope |
Interactive API docs (OpenAPI)
EduNest ships a hand-maintained OpenAPI 3.0 document and a Swagger UI page.
| Resource | URL | Notes |
|---|---|---|
| Swagger UI | /api-docs |
Swagger UI loaded from CDN, "Try it out" enabled |
| Raw OpenAPI JSON | /api/openapi.json |
The spec consumed by the docs page |
Both are protected by HTTP Basic Auth, enforced before the route is reachable. Credentials come from environment variables, with built-in fallbacks:
API_DOCS_USER=admin # default: admin
API_DOCS_PASS=Password@1 # default: Password@1
Both pages send noindex, nofollow (x-robots-tag) so they never appear in search engines. The spec is served force-static.
# Download the live spec (Basic Auth required)
curl -u "$API_DOCS_USER:$API_DOCS_PASS" \
http://localhost:3000/api/openapi.json -o edunest-openapi.json
The bundled
/api/openapi.jsondocuments the public, customer-portal, checkout and a representative slice of the admin endpoints. The REST API add-on publishes its own OpenAPI 3.1 spec separately at/api/v1/ext/api/openapi(see below).
Endpoint reference
The tables below list real route handlers under src/app/api/. List endpoints generally accept query params; :id / :slug are path params.
Storefront auth (public + portal)
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v1/portal/auth/register |
Register a learner (email OTP) |
POST |
/api/v1/portal/auth/verify-otp |
Verify OTP, sign in |
POST |
/api/v1/portal/auth/login |
Sign in |
POST |
/api/v1/portal/auth/logout |
Sign out |
GET |
/api/v1/portal/auth/social/providers |
List enabled social providers |
GET |
/api/v1/portal/me |
Current learner profile |
Courses (catalog)
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/courses |
List published courses |
GET |
/api/v1/courses/facets |
Filter facets (level, category, …) |
GET |
/api/v1/courses/:slug |
Course detail |
GET |
/api/v1/courses/:slug/reviews · POST |
List / submit course reviews |
POST |
/api/v1/courses/:slug/enroll |
Enroll in (free/open) course |
GET |
/api/v1/course-categories |
List categories |
GET |
/api/v1/learn/:slug |
Player payload (sections, lessons, progress) |
POST |
/api/v1/learn/:slug/lessons/:lessonId/complete |
Mark a lesson complete |
Enrollments & progress (portal)
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/portal/enrollments |
The learner's enrollments |
GET |
/api/v1/portal/dashboard |
Dashboard summary |
GET |
/api/v1/portal/grades |
Quiz/assignment grades |
GET |
/api/v1/portal/learning-paths |
Learning paths |
GET |
/api/v1/portal/wishlist |
Wishlist |
Orders & checkout
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v1/checkout |
Place an order |
GET |
/api/v1/checkout/methods |
Enabled payment methods |
POST |
/api/v1/checkout/coupon |
Apply a coupon to the cart |
POST |
/api/v1/checkout/verify |
Verify a gateway payment |
GET |
/api/v1/checkout/return/:provider |
Gateway redirect target |
GET |
/api/v1/portal/orders · /:id |
The learner's orders |
POST |
/api/v1/coupons/validate |
Validate a coupon |
POST |
/api/v1/gift-cards/validate |
Validate a gift card |
Customers (admin)
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/admin/customers · /:id |
List / fetch customers |
GET |
/api/v1/admin/learners |
List learners |
GET |
/api/v1/admin/orders · /:id |
List / manage orders |
GET/POST |
/api/v1/admin/coupons |
Manage coupons |
GET/POST |
/api/v1/admin/gift-cards |
Manage gift cards |
GET |
/api/v1/admin/dashboard · /api/v1/admin/revenue |
KPIs + revenue series |
Admin catalog & content
| Method | Path | Purpose |
|---|---|---|
GET/POST |
/api/v1/admin/courses · /:id |
Manage courses |
* |
/api/v1/admin/courses/:id/sections · /lessons |
Curriculum |
POST |
/api/v1/admin/courses/:id/status |
Publish / unpublish |
GET/POST |
/api/v1/admin/course-categories |
Categories |
GET/POST |
/api/v1/admin/instructors |
Instructors |
GET/POST |
/api/v1/admin/quizzes · /surveys · /bundles |
Assessments & bundles |
GET/POST |
/api/v1/admin/pages · /blogs · /faqs · /gallery |
CMS content |
GET/POST |
/api/v1/admin/settings/:section |
Read / write a settings section |
License
| Method | Path | Purpose |
|---|---|---|
GET |
/api/license/status |
Public license status (for the frontend banner) |
GET/POST |
/api/v1/admin/license |
Admin: view / activate the domain license |
GET |
/api/v1/admin/addons/license |
Add-on entitlements |
REST API add-on (/api/v1/ext/api/v1/*)
These are dispatched through the catch-all /api/v1/ext/[addon]/[...path] route into the add-on's handler map. Every endpoint is read-only and requires the scope shown.
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET |
/api/v1/ext/api/openapi |
— (public) | The add-on's OpenAPI 3.1 spec |
GET |
/api/v1/ext/api/v1/courses |
courses |
List published courses |
GET |
/api/v1/ext/api/v1/courses/:slug |
courses |
Get a course by slug |
GET |
/api/v1/ext/api/v1/customers |
customers |
List members |
GET |
/api/v1/ext/api/v1/enrollments |
enrollments |
List enrollments |
GET |
/api/v1/ext/api/v1/orders |
orders |
List orders (transactions) |
List endpoints accept limit (≤ 100, default 50) and offset (default 0) and return an envelope:
{ "data": [ /* rows */ ], "limit": 50, "offset": 0 }
Request example (REST add-on)
curl https://your-domain.com/api/v1/ext/api/v1/courses?limit=10 \
-H "Authorization: Bearer edu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
{
"data": [
{
"id": 42,
"slug": "intro-to-data-science",
"title": "Intro to Data Science",
"level": "beginner",
"price_cents": 4999,
"currency": "USD",
"status": "published",
"rating_avg": 4.7,
"enrollment_count": 1280
}
],
"limit": 10,
"offset": 0
}
The same key also works via the X-API-Key header:
curl https://your-domain.com/api/v1/ext/api/v1/enrollments \
-H "X-API-Key: edu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Error responses
First-party routes return JSON { "error": "..." } with the appropriate HTTP status. The REST add-on uses the same shape:
| Code | Meaning |
|---|---|
400 |
Bad request / validation error |
401 |
Not signed in (missing/invalid session or API key) |
403 |
Forbidden — missing RBAC permission, missing API-key scope, or unlicensed add-on |
404 |
Resource not found |
500 |
Server error |
{ "error": "This key is missing the 'orders' scope." }
© CreativeCape Solutions · creative-cape.com · support@creative-cape.com