Newlege API Documentation
Programmatic access to your academy — students, courses, enrollments, and transactions. Built for backends, automations, and AI agents.
Introduction
The Newlege Public API lets you read and write your academy's data from any system you control: backends, scripts, automation tools, or AI agents like Claude and ChatGPT.
Every request is scoped to a single academy through its API key. The API can never return data belonging to another academy — isolation is enforced at the database layer.
https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1
Authentication
All requests must include a bearer token in the Authorization header. Generate keys in the dashboard under Settings → Integrations → Public API. The plaintext token is shown once on creation — store it in a secret manager.
Keys look like nl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/me \
-H "Authorization: Bearer nl_live_..."
Scopes
Each key carries a list of scopes. Endpoints reject requests whose key lacks the required scope with HTTP 403.
| Scope | Grants |
|---|---|
| students:read | List and read students |
| students:write | Invite new students (creates user + sends email) |
| courses:read | List/read courses, chapters and lessons |
| courses:write | Create courses, chapters and lessons |
| enrollments:read | List enrollments |
| enrollments:write | Enroll a student in a course |
| transactions:read | List billing transactions |
Rate limits
Default limit: 60 requests per minute per key. Every response includes X-RateLimit-Limit and X-RateLimit-Remaining. Exceeding the limit returns HTTP 429 with error code rate_limited.
Errors
Errors use a stable envelope:
{
"error": {
"code": "forbidden_scope",
"message": "Missing required scope: students:read"
},
"request_id": "b3a1..."
}
| Code | HTTP | Meaning |
|---|---|---|
| unauthorized | 401 | Missing, invalid, expired, or revoked key |
| forbidden_scope | 403 | Key lacks the scope required by the endpoint |
| not_found | 404 | Resource does not exist in this academy |
| validation_error | 400 | Request body or query parameters are invalid |
| rate_limited | 429 | Exceeded the per-minute limit for this key |
| internal | 500 | Unexpected server error — retry with backoff |
Pagination
List endpoints accept limit (max 100, default 50) and cursor. The response includes pagination.next_cursor when more results exist. Pass that value back as cursor to fetch the next page.
curl "https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/students?limit=25&cursor=2025-06-01T10:00:00Z" \
-H "Authorization: Bearer nl_live_..."
GET /me
Returns the academy associated with the current key, plus the key's scopes. Useful for health checks and key validation.
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/me \
-H "Authorization: Bearer nl_live_..."
{
"data": {
"academy_id": "f2e486a9-...",
"academy_name": "Itai Barak Academy",
"academy_slug": "itai-barak",
"plan": "premium",
"scopes": ["students:read", "courses:read"]
},
"request_id": "..."
}
Students
List students — GET /students
Requires students:read. Returns members of the academy with the student role.
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/students \
-H "Authorization: Bearer nl_live_..."
{
"data": [
{
"id": "8c1d...",
"email": "student@example.com",
"full_name": "John Doe",
"phone": "+972501234567",
"status": "active",
"created_at": "2025-06-01T10:00:00Z"
}
],
"pagination": { "has_more": false, "next_cursor": null },
"request_id": "..."
}
Get student — GET /students/{id}
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/students/8c1d... \
-H "Authorization: Bearer nl_live_..."
Invite student — POST /students
Requires students:write. Creates a new user (if needed), adds them to the academy as a pending member, optionally enrolls them in one or more courses, and sends a branded email with a password-setup or join-confirmation link.
| Field | Type | Required | Description |
|---|---|---|---|
| string | yes | Student's email address | |
| full_name | string | yes | Display name (max 120 chars) |
| phone | string | no | Phone in international format |
| course_ids | uuid[] | no | Courses to enroll the student into (must belong to your academy) |
| expires_at | ISO 8601 | no | Optional access expiry for the enrollments |
| send_email | boolean | no | Send invitation email. Default: true |
curl -X POST https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/students \
-H "Authorization: Bearer nl_live_..." \
-H "Content-Type: application/json" \
-d '{
"email": "new.student@example.com",
"full_name": "Dana Cohen",
"phone": "+972501234567",
"course_ids": ["COURSE_UUID_1"],
"send_email": true
}'
{
"data": {
"id": "8c1d...",
"email": "new.student@example.com",
"full_name": "Dana Cohen",
"phone": "+972501234567",
"status": "pending",
"is_new_user": true,
"enrolled_course_ids": ["COURSE_UUID_1"],
"invitation_link": "https://your-academy.newlege.co.il/student/auth?type=set-password&token_hash=..."
},
"request_id": "..."
}
Returns plan_limit_reached (HTTP 403) when the academy has reached its student quota for its current plan.
Courses
List courses — GET /courses
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/courses \
-H "Authorization: Bearer nl_live_..."
Get course — GET /courses/{id}
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/courses/COURSE_ID \
-H "Authorization: Bearer nl_live_..."
Create course — POST /courses
Requires courses:write. New courses are created as drafts by default (hidden from students).
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | yes | Course title |
| description | string | no | Marketing description |
| slug | string | no | URL slug (auto-generated if omitted) |
| price | number | no | Default 0 |
| payment_type | string | no | 'one_time' (default) or 'subscription' |
| is_published | boolean | no | Default false — keep drafts hidden from students |
curl -X POST https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/courses \
-H "Authorization: Bearer nl_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Mastering Public Speaking",
"description": "From stage fright to standing ovation in 8 weeks.",
"price": 499,
"payment_type": "one_time"
}'
Chapters
Chapters group lessons inside a course. Position is auto-assigned to the next available index if omitted.
List chapters — GET /courses/{course_id}/chapters
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/courses/COURSE_ID/chapters \
-H "Authorization: Bearer nl_live_..."
Create chapter — POST /courses/{course_id}/chapters
Requires courses:write.
curl -X POST https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/courses/COURSE_ID/chapters \
-H "Authorization: Bearer nl_live_..." \
-H "Content-Type: application/json" \
-d '{ "title": "Week 1 — Foundations" }'
{
"data": {
"id": "ch_uuid",
"course_id": "COURSE_ID",
"title": "Week 1 — Foundations",
"position": 0,
"created_at": "2026-06-15T10:00:00Z"
},
"request_id": "..."
}
Lessons
Lessons live inside a chapter. Each lesson has a content_type describing how to render it.
List lessons — GET /chapters/{chapter_id}/lessons
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/chapters/CHAPTER_ID/lessons \
-H "Authorization: Bearer nl_live_..."
Create lesson — POST /chapters/{chapter_id}/lessons
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | yes | Lesson title |
| content_type | enum | yes | video | text | file | audio | embed | live |
| content_url | string | no | URL of the video / file / embed |
| content_text | string | no | HTML/markdown body for text lessons |
| description | string | no | Short description shown in the player |
| position | number | no | Order within the chapter (auto-appended if omitted) |
| duration_seconds | number | no | Lesson length in seconds |
| is_free_gift | boolean | no | Free preview / gift lesson |
curl -X POST https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/chapters/CHAPTER_ID/lessons \
-H "Authorization: Bearer nl_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Intro video",
"content_type": "video",
"content_url": "https://vimeo.com/123456789",
"duration_seconds": 540
}'
Enrollments
List — GET /enrollments
Optional filters: course_id, student_id.
curl "https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/enrollments?course_id=COURSE_ID" \
-H "Authorization: Bearer nl_live_..."
Create — POST /enrollments
Grants a student access to a course. Both must already exist in this academy.
curl -X POST https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/enrollments \
-H "Authorization: Bearer nl_live_..." \
-H "Content-Type: application/json" \
-d '{ "student_id": "STUDENT_UUID", "course_id": "COURSE_UUID" }'
Transactions
List — GET /transactions
curl https://cuabhknytckerifjaple.supabase.co/functions/v1/public-api/v1/transactions \
-H "Authorization: Bearer nl_live_..."
Use with Claude / GPT
Both Claude Projects and OpenAI's custom GPTs support adding HTTP tools. Configure a tool that calls the endpoints above using your API key in the Authorization header. Once added, you can ask the model things like "list my newest 10 students" or "enroll user X in course Y" in natural language.
A native MCP server is coming in Phase 2 — it will expose every endpoint as a typed MCP tool so Claude Desktop and Cursor can use it without manual configuration.
Use with Zapier / Make / n8n
Use the generic HTTP / Webhook action. Set the URL to one of the endpoints above, add the Authorization: Bearer nl_live_... header, and for POSTs send JSON. Example trigger: "When a row is added in Google Sheets → POST /enrollments".
Changelog
v1.1 — Write endpoints: POST /students (invite), POST /courses, POST /courses/{id}/chapters, POST /chapters/{id}/lessons. New scope courses:write.
v1.0 — Initial release. Endpoints: /me, /students, /courses, /enrollments, /transactions.