Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DerBasilisk/SEA-ServicioEvaluaconAsistida/llms.txt

Use this file to discover all available pages before exploring further.

A Lesson is a timed, scored practice session drawn from a pool of typed quiz questions. Sealearn’s adaptive engine analyses each user’s weekly activity, current streak, and recent scores before every session and dynamically chooses the number of questions, the difficulty mix, and the XP multiplier. This means no two sessions feel identical, and the challenge scales automatically with the learner’s performance.

Lesson types

TypeDescription
lessonStandard lesson with a hand-curated or AI-supplemented question pool.
checkpointEnd-of-unit evaluation with a harder question mix.
reviewSpaced-repetition replay triggered when a previous completion is due for review.
ai_generatedQuestions are generated fresh by the AI each time the lesson is started, using the subject and lesson context.

Lesson model fields

unit
ObjectId
required
Reference to the parent Unit document.
name
string
required
Display name of the lesson.
description
string
Optional description. Maximum 500 characters.
order
number
required
Position of the lesson within its unit. Combined with unit, must be unique.
type
string
One of lesson, checkpoint, review, ai_generated. Defaults to lesson.
xpReward
number
Base XP awarded for completing the lesson. Defaults to 10. The adaptive engine multiplies this before crediting the user.
gemsReward
number
Gems awarded on completion. Defaults to 0. Perfect scores (100%) add an extra 5 gems on top.
questionCount
number
Base number of questions per session (3–20). The adaptive engine uses this as a starting point, then scales the actual count between 5 and 18. Defaults to 5.
timeLimit
number | null
Optional session time limit in seconds. null means no limit. Defaults to null.
difficulty
string
Base difficulty: easy, medium, or hard. The adaptive engine may shift this up or down by one level depending on the user’s activity score.
theory
object
Optional mini-reading shown before the exercises.
aiTopicHint
string
Specific topic hint passed to the AI when generating questions. Defaults to the lesson name.
isActive
boolean
Soft-delete flag. Defaults to true.

Adaptive engine

When a user starts a lesson, getAdaptiveConfig computes an activity score (0–100) from three signals:
SignalWeightHow it is measured
Lessons completed in the last 7 days40%Up to 14 lessons/week maps linearly to 100.
Current streak30%Up to 30 days maps linearly to 100.
Average score of last 10 completions30%Raw percentage (0–100). Defaults to 50 when no history exists.
The resulting activityScore drives three adaptive parameters:
Activity scorequestionCountdifficultyeasyRatio / hardRatio
0–30 (low activity)5–8Escalated one level above base20% easy / 50% hard
31–60 (moderate)9–13Base difficulty unchanged33% easy / 33% hard
61–100 (high activity)14–18Lowered one level below base50% easy / 20% hard
questionCount is always clamped between 5 and 18.

Endpoints

GET /api/lessons/review

Returns up to 10 completed lessons that are due for spaced-repetition review today (i.e. their spacedRepetition.nextReviewDate is on or before the current date). Authentication: Bearer token required.
curl https://api.sealearn.app/api/lessons/review \
  -H "Authorization: Bearer <token>"
ok
boolean
true on success.
data
object[]
Array of review items.
Example response
{
  "ok": true,
  "data": [
    {
      "lesson": {
        "_id": "665f3c4d5e6f7a8b9c0f1a2b",
        "name": "Adding and Subtracting",
        "xpReward": 10,
        "unit": "665f2b3c4d5e6f7a8b9c0e1f"
      },
      "nextReviewDate": "2025-06-07T00:00:00.000Z",
      "repetitions": 3
    }
  ]
}

GET /api/lessons/:id

Returns a single active lesson populated with its parent unit and the unit’s parent subject (name, color, icon). Also includes the requesting user’s current status, best score, and completion count for that lesson. Authentication: Bearer token required. Path parameters
id
string
required
MongoDB ObjectId of the lesson.
curl https://api.sealearn.app/api/lessons/665f3c4d5e6f7a8b9c0f1a2b \
  -H "Authorization: Bearer <token>"
ok
boolean
true on success.
data
object

POST /api/lessons/:id/start

Triggers the adaptive engine, selects (or generates) questions, records a new in-progress session, and returns everything the client needs to render the lesson UI: the question list, AI-generated theory slides, and the adaptive configuration used. For lesson type, if the question pool is smaller than the adaptive questionCount, the API automatically calls the AI to generate the missing questions and saves them for future use before proceeding. Authentication: Bearer token required. The user must have at least 1 heart remaining. Path parameters
id
string
required
MongoDB ObjectId of the lesson to start.
curl -X POST https://api.sealearn.app/api/lessons/665f3c4d5e6f7a8b9c0f1a2b/start \
  -H "Authorization: Bearer <token>"
ok
boolean
true on success.
data
object
Example response
{
  "ok": true,
  "data": {
    "lesson": {
      "_id": "665f3c4d5e6f7a8b9c0f1a2b",
      "name": "Adding and Subtracting",
      "xpReward": 10,
      "timeLimit": null,
      "type": "lesson"
    },
    "questions": [ /* ... */ ],
    "theorySlides": [ /* ... */ ],
    "totalQuestions": 9,
    "hearts": 5,
    "adaptive": {
      "questionCount": 9,
      "difficulty": "easy",
      "activityScore": 45
    }
  }
}
For multiple_choice questions the options array is shuffled randomly before being sent. For order_items the array is exposed as shuffledItems (correct order removed). For match_pairs the pairs are split into leftItems and rightItems, each independently shuffled. For sentence_builder the wordBank is shuffled.
If the user’s hearts.current is 0, the endpoint returns 403 Forbidden with the message “No tenés corazones para iniciar una lección”. Hearts refill automatically 30 minutes after reaching zero, or can be refilled immediately with gems via POST /api/progress/refill-hearts.

Question answer formats

Each question object in the questions array has a type field. Use the correct answer shape when calling POST /api/lessons/:id/answer.
The options array is delivered as [{ _id, text }, ...] (shuffled). Submit the _id of the option you believe is correct.
{
  "questionId": "665fabc...",
  "answer": "665fopt1..."
}
Submit a JavaScript boolean (true or false). String values "true" and "false" are also accepted and coerced automatically.
{
  "questionId": "665fabc...",
  "answer": true
}
Submit the word or phrase that fills the blank. Matching is case-insensitive and accent-insensitive — “ecuation” and “Ecuación” are treated as equivalent. If the strict comparison fails, the AI is called as a fallback evaluator.
{
  "questionId": "665fabc...",
  "answer": "photosynthesis"
}
The question delivers a shuffledItems array of strings. Submit those same strings in the order you believe is correct.
{
  "questionId": "665fabc...",
  "answer": ["First step", "Second step", "Third step"]
}
The question delivers leftItems and rightItems, each as [{ _id, text }] arrays (shuffled independently). Both arrays are derived from the same underlying pair documents, so a left item and its matching right item share the same _id. Submit an array of { leftId, rightId } objects where you set leftId to a left item’s _id and rightId to the _id of the right item you believe it matches. A submission is correct when every leftId equals its corresponding rightId (i.e. they originate from the same pair).
{
  "questionId": "665fabc...",
  "answer": [
    { "leftId": "665fpair1", "rightId": "665fpair1" },
    { "leftId": "665fpair2", "rightId": "665fpair2" }
  ]
}
The question delivers a shuffled wordBank array of strings. Submit the words in the correct order as an array of strings.
{
  "questionId": "665fabc...",
  "answer": ["The", "mitochondria", "is", "the", "powerhouse"]
}
Submit any string. The AI evaluates it against the question’s evaluationCriteria and maxScore. The response shape differs from other types — see the POST /api/lessons/:id/answer response section.
{
  "questionId": "665fabc...",
  "answer": "Photosynthesis converts light energy into chemical energy stored in glucose."
}
Submit the string exactly as it must appear. Comparison is strict (case-sensitive, whitespace-sensitive). A wrong answer costs a heart.
{
  "questionId": "665fabc...",
  "answer": "print(\"Hello, world!\")"
}
Code execution happens on the client (via a Pyodide sandbox or similar). Submit the evaluation result — not the raw code. A wrong answer costs a heart.
{
  "questionId": "665fabc...",
  "answer": {
    "passed": true,
    "passedCount": 3,
    "totalCount": 3,
    "code": "def add(a, b):\n    return a + b"
  }
}

POST /api/lessons/:id/answer

Submits one answer and returns whether it was correct, the explanation, and the XP earned for that question. An incorrect answer deducts one heart for every question type except free_text, which is AI-evaluated and never penalises hearts. typing and code_python handle heart deduction inside their own response branch but follow the same rule. Authentication: Bearer token required. Path parameters
id
string
required
MongoDB ObjectId of the lesson the session belongs to.
Request body
questionId
string
required
ObjectId of the question being answered.
answer
any
required
The answer value. See the question type accordion above for the correct shape per type.
hintUsed
boolean
If true, XP earned for a correct answer is halved (xpValue * 0.5).
typingStats
object
Optional typing performance metrics (WPM, accuracy, etc.) for typing questions. Stored alongside the attempt record.
curl -X POST https://api.sealearn.app/api/lessons/665f3c4d5e6f7a8b9c0f1a2b/answer \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "questionId": "665fabc123def456",
    "answer": "665fopt1abc",
    "hintUsed": false
  }'
Standard response (all types except free_text)
ok
boolean
true on success.
data
object
free_text response
ok
boolean
true on success.
data
object
code_python response
ok
boolean
true on success.
data
object

POST /api/lessons/:id/complete

Marks the current in-progress session as completed, calculates the final score, awards adaptive XP and gems, updates the user’s streak, adds XP to the weekly league, unlocks the next lesson if eligibility criteria are met, and checks for new achievement unlocks. Authentication: Bearer token required. An active in-progress session must exist for this lesson. Path parameters
id
string
required
MongoDB ObjectId of the lesson to complete.
curl -X POST https://api.sealearn.app/api/lessons/665f3c4d5e6f7a8b9c0f1a2b/complete \
  -H "Authorization: Bearer <token>"
ok
boolean
true on success.
data
object
The next lesson in the unit unlocks when the user has completed the current lesson at least 4 times. Completion is counted per unique successful call to this endpoint.

POST /api/lessons/:id/abandon

Abandons an in-progress session. The lesson’s status is reset to available and the current session attempts are cleared. No XP is awarded and no hearts are penalised. Authentication: Bearer token required. Path parameters
id
string
required
MongoDB ObjectId of the lesson to abandon.
curl -X POST https://api.sealearn.app/api/lessons/665f3c4d5e6f7a8b9c0f1a2b/abandon \
  -H "Authorization: Bearer <token>"
Example response
{ "ok": true, "message": "Lección abandonada" }

Build docs developers (and LLMs) love