Getting Started
All endpoints are prefixed with
/api. Requests and responses use JSON. Authentication uses Bearer tokens obtained from POST /api/auth/login.Quick reference
Base URL
https://app.studuet.com/api
Auth header
Authorization: Bearer <token>
Content-Type
application/json
Token TTL
7 days (JWT, HS256)
# Example authenticated request
curl -X GET https://app.studuet.com/api/users/profile \
-H "Authorization: Bearer eyJhbGci..." \
-H "Content-Type: application/json"
Standard response envelope
{
"user": { ... }, // or "data", "sessions", "decks" etc.
"error": "..." // present only on failure
}
Errors & Status Codes
All errors return a JSON body with an
error string. Use the HTTP status code to determine the error class.| Status | Meaning | Common cause |
|---|---|---|
| 400 | Bad Request | Missing or invalid body fields |
| 401 | Unauthorized | Missing, expired, or invalid token |
| 403 | Forbidden | Insufficient role (e.g. student hitting admin route) |
| 404 | Not Found | Resource does not exist or belongs to another user |
| 409 | Conflict | Duplicate entry (e.g. email already registered) |
| 429 | Rate Limited | Too many requests — back off and retry |
| 500 | Server Error | Unexpected server fault — contact support |
Authentication
Register, log in, and manage sessions. All other endpoints require the JWT returned here.
POST
/auth/register
Create a new account
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| full_name | string | Yes | Display name |
| string | Yes | Unique email address | |
| password | string | Yes | Min 8 characters |
| role | string | No | student (default) or tutor |
Response 201
{ "token": "eyJhbGci...", "user": { "id": 42, "role": "student", ... } }
POST
/auth/login
Obtain a JWT token
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Registered email | |
| password | string | Yes | Account password |
Response 200
{ "token": "eyJhbGci...", "user": { "id": 42, "email": "...", "role": "student" } }
GET
/auth/me
Return current user from token
Auth
▾
Response 200
{ "user": { "id": 42, "full_name": "Alex", "role": "student", "email_verified": true } }
POST
/auth/logout
Invalidate current session
Auth
▾
Response 200
{ "ok": true }
Users
Read and update the authenticated user's profile, password, avatar, and tutor-specific fields. Includes document uploads for tutor verification.
GET
/users/profile
Get full profile + tutor data
Auth
▾
Response 200
{
"user": {
"id": 42, "full_name": "Alex", "email": "...", "role": "tutor",
"specialisation": "GMAT", "subjects": ["Quant"],
"hourly_rate": 65, "bio": "...", "is_verified": false,
"approval_status": "pending", "cv_url": "...", "certificate_url": "..."
}
}
PATCH
/users/profile
Update profile fields
Auth
▾
Body (all optional)
| Field | Type | Description |
|---|---|---|
| full_name | string | Display name |
| string | Must be unique | |
| phone | string | Contact number |
| timezone | string | IANA timezone e.g. Europe/London |
| specialisation | string | Tutors only — headline specialisation |
| subjects | array | Tutors only — list of subjects |
| hourly_rate | number | Tutors only — rate in GBP |
| bio | string | Tutors only — profile bio |
| cv_url | string | Tutors only — uploaded CV URL |
| certificate_url | string | Tutors only — qualification cert URL |
| id_document_url | string | Tutors only — photo ID / DBS URL |
| reference_contact | string | Tutors only — professional reference info |
PATCH
/users/password
Change account password
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| current_password | string | Yes | Current password |
| new_password | string | Yes | New password (min 8 chars) |
POST
/users/upload-document
Upload a tutor verification document
Auth
▾
Multipart/form-data upload. Returns a URL to use in profile PATCH.
Form field
| Field | Type | Description |
|---|---|---|
| file | file | PDF, JPG, PNG, DOCX — max 10 MB |
Response 200
{ "url": "/uploads/tutor-docs/abc123.pdf" }
GET
/users/tutors
List approved tutors (public)
▾
Query params
| Param | Type | Description |
|---|---|---|
| subject | string | Filter by subject |
| limit | number | Max results (default 20) |
Response 200
{ "tutors": [{ "id": 5, "full_name": "Dr. Sarah", "rating_avg": 4.9, ... }] }
CLP Profiles
Cognitive Learning Profile — the core of Studuet's adaptive engine. Six dimensions scored 0–100:
visual_format, attention_span, processing_speed, cognitive_load, stress_response, social_learning.
GET
/clp
Fetch the authenticated user's CLP profile
Auth
▾
Response 200
{
"profile": {
"visual_format": 72, "attention_span": 58, "processing_speed": 65,
"cognitive_load": 80, "stress_response": 45, "social_learning": 60,
"profile_type": "Deep Analyst", "assessment_count": 1
}
}
POST
/clp/save
Save or update a CLP profile
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| visual_format | number 0–100 | Yes | Visual vs verbal learning preference |
| attention_span | number 0–100 | Yes | Session length / pacing preference |
| processing_speed | number 0–100 | Yes | Content delivery speed preference |
| cognitive_load | number 0–100 | Yes | Complexity tolerance |
| stress_response | number 0–100 | Yes | Pressure / challenge preference |
| social_learning | number 0–100 | Yes | Collaborative vs solo preference |
| profile_type | string | No | e.g. "Deep Analyst" |
| raw_answers | object | No | Full assessment answer payload |
POST
/clp/infer
Infer CLP from session behaviour (system)
Auth
▾
Called internally after sessions to update the Bayesian CLP estimate. Sends recent session signals to the ILE engine and updates clp_profiles without overwriting formal assessment results.
Sessions
Book, manage, and query tutoring sessions. Sessions link a student, tutor, subject, date/time, and Jitsi video room.
GET
/sessions
List sessions for current user
Auth
▾
Query params
| Param | Type | Description |
|---|---|---|
| status | string | pending | confirmed | completed | cancelled |
| limit | number | Max results (default 20) |
| page | number | Page number (default 1) |
Response 200
{ "sessions": [{ "id": 1, "subject": "GMAT Quant", "status": "confirmed", "meeting_url": "..." }] }
POST
/sessions
Book a new session
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| tutor_id | number | Yes | ID of the tutor |
| subject | string | Yes | Subject / topic |
| session_date | string | Yes | ISO date e.g. 2026-05-01 |
| start_time | string | Yes | Time e.g. 14:00 |
| duration_min | number | No | Duration in minutes (default 60) |
| notes | string | No | Student notes for the tutor |
PATCH
/sessions/:id/status
Update session status
Auth
▾
Body
| Field | Type | Description |
|---|---|---|
| status | string | confirmed | completed | cancelled |
| rating | number 1–5 | Student rating (on completion) |
| feedback | string | Student feedback text |
GET
/sessions/:id/video-room
Get Jitsi room details for a session
Auth
▾
Response 200
{ "room_name": "studuet-session-xyz", "jwt": "...", "domain": "video.studuet.com" }
Flashcards
SM-2 spaced repetition flashcard system. Organise cards into decks, review due cards, and track mastery.
GET
/flashcards/decks
List all decks for current user
Auth
▾
Response 200
{ "decks": [{ "id": 1, "name": "GMAT Vocab", "card_count": 48, "due_count": 12 }] }
POST
/flashcards/decks
Create a new deck
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Deck name |
| subject | string | No | Associated subject |
| description | string | No | Deck description |
POST
/flashcards/decks/:id/cards
Add a card to a deck
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| front | string | Yes | Question / prompt side |
| back | string | Yes | Answer side |
| hint | string | No | Optional hint text |
POST
/flashcards/review
Submit a card review (SM-2)
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| card_id | number | Yes | Card being reviewed |
| quality | number 0–5 | Yes | SM-2 quality rating (0=blackout, 5=perfect) |
Response 200
{ "next_review": "2026-04-20", "interval_days": 7, "easiness": 2.6 }
GET
/flashcards/due
Get cards due for review today
Auth
▾
Response 200
{ "cards": [{ "id": 101, "front": "What is...", "back": "...", "deck_name": "GMAT Vocab" }] }
Mock Exams
Timed practice exams drawn from the question bank. Track attempt history and score trends.
POST
/mock-exams/start
Start a new mock exam attempt
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| subject | string | Yes | Subject / exam type |
| question_count | number | No | Number of questions (default 10) |
| difficulty | string | No | easy | medium | hard | mixed |
Response 200
{ "attempt_id": 88, "questions": [{ "id": 1, "text": "...", "options": ["A","B","C","D"] }] }
POST
/mock-exams/:id/submit
Submit answers and get results
Auth
▾
Body
{ "answers": { "1": "B", "2": "A", ... } }
Response 200
{ "score_pct": 72, "correct": 18, "total": 25, "xp_earned": 360, "results": [...] }
GET
/mock-exams/history
List past exam attempts
Auth
▾
Response 200
{ "attempts": [{ "id": 88, "subject": "GMAT", "score_pct": 72, "created_at": "2026-04-10" }] }
Study Logs
Log independent study sessions and retrieve aggregated study statistics used by the ILE engine.
POST
/study/log
Log a study session
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| subject | string | Yes | Subject studied |
| duration_min | number | Yes | Time studied in minutes |
| mood | number 1–5 | No | Self-reported focus/mood score |
| notes | string | No | Session notes |
GET
/study/stats
Get study statistics summary
Auth
▾
Response 200
{ "total_hours": 142, "this_week_min": 320, "streak_days": 7, "by_subject": [...] }
Exam Questions
Access the curated question bank used for mock exams and practice. Filterable by subject, difficulty, and topic.
GET
/exams/questions
Query the question bank
Auth
▾
Query params
| Param | Type | Description |
|---|---|---|
| subject | string | e.g. GMAT, IELTS |
| difficulty | string | easy | medium | hard |
| topic | string | Sub-topic filter |
| limit | number | Max results (default 20) |
GET
/exams/subjects
List all available subjects
▾
Response 200
{ "subjects": ["GMAT", "GRE", "IELTS", "SAT", "A-Levels", "GCSE"] }
Materials
Upload and manage study resources used by AI Tutor (Uris) for adaptive coaching. Approved materials feed the RAG knowledge bank.
POST
/materials/upload
Upload a study resource (multipart)
Auth
▾
Accepts PDF, DOCX, TXT. Approved resources are used by Uris for contextual tutoring.
Form fields
| Field | Type | Description |
|---|---|---|
| file | file | Document file — max 20 MB |
| subject | string | Associated subject |
| title | string | Resource title |
GET
/materials
List available materials
Auth
▾
Response 200
{ "materials": [{ "id": 3, "title": "GMAT OG", "subject": "GMAT", "status": "approved" }] }
XP & Leaderboard
XP (experience points) are awarded for sessions, mock exams, flashcard reviews, and study logs. Used for squad leaderboards and competitions.
GET
/xp/summary
Get XP totals and level for current user
Auth
▾
Response 200
{ "total_xp": 4820, "level": 12, "level_label": "Scholar", "next_level_xp": 5000 }
GET
/xp/leaderboard
Global XP leaderboard
Auth
▾
Query params
| Param | Description |
|---|---|
| period | week | month | all (default week) |
| limit | Top N results (default 10) |
Study Squads
Collaborative study groups with shared chat, group XP leaderboards, and group video meetings.
GET
/squads
List squads the user belongs to
Auth
▾
Response 200
{ "squads": [{ "id": 1, "name": "GMAT Grinders", "member_count": 6, "my_rank": 2 }] }
POST
/squads
Create a new study squad
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Squad display name |
| subject | string | No | Primary focus subject |
| max_members | number | No | Max size (default 10) |
GET
/squads/:id/chat
Get squad chat messages
Auth
▾
Query params
| Param | Description |
|---|---|
| before | ISO timestamp — fetch messages older than this |
| limit | Max messages (default 50) |
POST
/squads/:id/start-meeting
Start a squad video meeting
Auth
▾
Response 200
{ "meeting_url": "https://video.studuet.com/squad-xyz", "meeting_uid": "abc123" }
Competitions
Platform-wide and squad competitions with prize pools, leaderboards, and XP multipliers.
GET
/competitions/active
List currently active competitions
Auth
▾
Response 200
{ "competitions": [{ "id": 2, "name": "April Sprint", "ends_at": "2026-04-30", "prize": "Free session" }] }
POST
/competitions/:id/enter
Enter a competition
Auth
▾
Response 200
{ "ok": true, "entry_id": 88 }
AI Tutor (Uris)
Conversational AI tutoring powered by Claude. Uris adapts tone, depth, and pacing to each student's CLP profile and responds with contextual knowledge from uploaded materials.
POST
/ai-tutor/chat
Send a message to Uris AI
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | Student's question or message |
| session_id | number | No | Link chat to a tutoring session |
| subject | string | No | Narrow Uris context to a subject |
| history | array | No | Prior turns [{role, content}] |
Response 200
{ "reply": "Great question! The GMAT Quant section...", "sources": ["OG Guide p.142"] }
ILE — Intelligent Learning Engine
The ILE adapts session pacing, content density, and tutor matching weights based on real-time CLP signals from study behaviour.
GET
/ile/config
Get ILE adaptation config for current user
Auth
▾
Response 200
{
"recommended_session_length": 45,
"content_density": "medium",
"pacing": "methodical",
"best_study_window": "morning"
}
POST
/ile/adapt
Push a behaviour signal to update ILE state
Auth
▾
Body
| Field | Type | Description |
|---|---|---|
| signal_type | string | session_exit | card_struggle | exam_score | study_mood |
| value | number | Signal magnitude (meaning depends on type) |
| subject | string | Context subject |
Analytics
Admin and institution-level analytics. Tutor and student engagement dashboards, cohort performance, and revenue trends.
GET
/analytics/dashboard
Platform analytics summary
Admin
▾
Response 200
{
"total_sessions": 1204, "avg_score": 71.4,
"top_tutors": [...], "revenue_by_month": [...]
}
GET
/analytics/cohort
Cohort performance breakdown
Admin
▾
Query params
| Param | Description |
|---|---|
| subject | Filter by subject |
| period | week | month | quarter |
Payments
Stripe-backed payment processing for session bookings, subscriptions, and tutor payouts.
POST
/payments/checkout
Create a Stripe checkout session
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| session_id | number | Yes | Session to pay for |
| success_url | string | No | Redirect after successful payment |
| cancel_url | string | No | Redirect if user cancels |
Response 200
{ "checkout_url": "https://checkout.stripe.com/pay/cs_..." }
GET
/payments/plans
List available subscription plans
▾
Response 200
{ "plans": [{ "id": "pro", "name": "Student Pro", "price_gbp": 19, "interval": "month" }] }
Notifications
In-app notifications for bookings, approvals, squad activity, and system messages. Supports real-time SSE streaming.
GET
/notifications
List notifications for current user
Auth
▾
Query params
| Param | Description |
|---|---|
| unread | true to return only unread notifications |
| limit | Max results (default 20) |
Response 200
{ "notifications": [{ "id": 5, "type": "booking_confirmed", "message": "...", "read": false }] }
PATCH
/notifications/:id/read
Mark a notification as read
Auth
▾
Response 200
{ "ok": true }
GET
/notifications/stream
Server-sent events stream
Auth
▾
Returns a persistent SSE connection. Each event is a JSON-encoded notification object. Keep-alive pings every 30s.
# JavaScript
const es = new EventSource('/api/notifications/stream?token=...');
es.onmessage = e => console.log(JSON.parse(e.data));
Support Tickets
Create and track support requests. Admin staff can respond and update ticket status.
POST
/support-tickets
Create a new support ticket
Auth
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| subject | string | Yes | Ticket subject |
| category | string | Yes | Payment | Account | Technical | Booking | General |
| priority | string | No | low | medium | high | urgent |
| body | string | Yes | Description of the issue |
GET
/support-tickets
List tickets for current user
Auth
▾
Response 200
{ "tickets": [{ "id": 3, "subject": "Payment issue", "status": "open", "priority": "high" }] }
Admin
Admin and manager-only endpoints for platform management. Requires
admin or manager role.
GET
/admin/stats
Platform overview statistics
Admin
▾
Response 200
{
"total_students": 1420, "total_tutors": 38,
"total_sessions": 4820, "total_revenue": 92400,
"clp_total_profiles": 980, "sessions_today": 24
}
GET
/admin/tutors
List all tutors with profile & approval data
Admin
▾
Query params
| Param | Description |
|---|---|
| status | pending | approved | rejected |
| search | Search by name or email |
Response 200
{ "tutors": [{ "id": 5, "full_name": "Dr. Sarah", "approval_status": "pending", "cv_url": "..." }] }
GET
/admin/tutors/:id
Full tutor profile for review
Admin
▾
Response 200
{
"tutor": {
"id": 5, "full_name": "Dr. Sarah", "bio": "...",
"cv_url": "...", "certificate_url": "...",
"id_document_url": "...", "reference_contact": "...",
"approval_status": "pending", "rejection_note": null
}
}
PATCH
/admin/tutors/:id/verify
Approve or reject a tutor
Admin
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| verified | boolean | Yes | true = approve, false = reject |
| rejection_note | string | No* | Required when rejecting — sent to tutor via email |
GET
/admin/users
List all users with filtering
Admin
▾
Query params
| Param | Description |
|---|---|
| role | student | tutor | admin |
| search | Search by name or email |
| page | Pagination page (default 1) |
| limit | Results per page (max 200) |
PATCH
/admin/users/:id
Update user status or role
Admin
▾
Body
| Field | Type | Description |
|---|---|---|
| is_active | boolean | Activate or suspend the account |
| role | string | Change role: student | tutor | admin |
GET
/admin/settings
Fetch all platform settings
Admin
▾
Response 200
{ "settings": [{ "setting_key": "xp_per_session_hour", "setting_value": "100", "category": "xp" }] }
PATCH
/admin/settings/:key
Update a platform setting
Admin
▾
Body
| Field | Type | Required | Description |
|---|---|---|---|
| value | string | number | boolean | Yes | New setting value |